int mmc_erase_blks(int dev_id, u32 addr, u32 size, int bootarea) { unsigned long ret; int i, j, result = 0; u8 val; u8 *ext_csd; u32 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; if (mmc_erase_start(card, blknr * MMC_BLOCK_SIZE) != MMC_ERR_NONE) { result = -__LINE__; goto done; } if (mmc_erase_end(card, (blknr + total_blks) * MMC_BLOCK_SIZE) != MMC_ERR_NONE) { result = -__LINE__; goto done; } if (mmc_erase(card, MMC_ERASE_NORMAL) != MMC_ERR_NONE) { result = -__LINE__; goto done; } 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] Erase %d blocks (%d bytes) from 0x%x successfully\n", dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE); } else { printf("[SD%d] Erase %d blocks (%d bytes) from 0x%x failed %d\n", dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE, result); } return result; }
/* call mmc block layer interface for userspace to do erase operate */ static int simple_mmc_erase_func(unsigned int start, unsigned int size) { struct msdc_host *host; /* emmc always in slot0 */ host = msdc_get_host(MSDC_EMMC,MSDC_BOOT_EN,0); BUG_ON(!host); BUG_ON(!host->mmc); BUG_ON(!host->mmc->card); mmc_claim_host(host->mmc); if (!mmc_can_trim(host->mmc->card)){ printk("emmc card can't support trim\n"); return 0; } mmc_erase(host->mmc->card, start, size, __MMC_TRIM_ARG); #if DEBUG_MMC_IOCTL printk("erase done....\n"); #endif mmc_release_host(host->mmc); return 0; }
void mlo_erase() { static unsigned MSG = 0xaabbccdd; int ret = 0; u8 val; /*Enable USB mux pin cfg enable USB clock */ enable_irqs(); if (usb_open(&usbdev)) return -1; ret = mmc_init(1); if (ret != 0){ printf("\n MMC init failed \n"); goto error; } ret = mmc_erase(1, (1024*128/MMC_BLOCK_SIZE), 1024*128); usb_write(&usbdev, &MSG, 4); /*power off PMIC */ printf("erase ret %d Powering off!\n", ret); select_bus(CFG_I2C_BUS, CFG_I2C_SPEED); val = SWITCH_OFF; i2c_write(TWL6030_PMC_ID, PHOENIX_DEV_ON, 1, &val, 1); /* we should never get here */ error: hang(); }
/* call mmc block layer interface for userspace to do erase operate */ static int simple_mmc_erase_func(unsigned int start, unsigned int size) { struct msdc_host *host; unsigned int arg; /* emmc always in slot0 */ host = msdc_get_host(MSDC_EMMC,MSDC_BOOT_EN,0); BUG_ON(!host); BUG_ON(!host->mmc); BUG_ON(!host->mmc->card); mmc_claim_host(host->mmc); if(mmc_can_discard(host->mmc->card)) { arg = __MMC_DISCARD_ARG; }else if (host->mmc->card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN){ /* for Hynix eMMC chip£¬do trim even if it is MMC_QUIRK_TRIM_UNSTABLE */ arg = __MMC_TRIM_ARG; }else if(mmc_can_erase(host->mmc->card)){ /* mmc_erase() will remove the erase group un-aligned part, * msdc_command_start() will do trim for old combo erase un-aligned issue */ arg = __MMC_ERASE_ARG; }else { printk("[%s]: emmc card can't support trim / discard / erase\n", __func__); goto end; } printk("[%s]: start=0x%x, size=%d, arg=0x%x, can_trim=(0x%x),EXT_CSD_SEC_GB_CL_EN=0x%x\n", __func__, start, size, arg, host->mmc->card->ext_csd.sec_feature_support, EXT_CSD_SEC_GB_CL_EN); mmc_erase(host->mmc->card, start, size, arg); #if DEBUG_MMC_IOCTL printk("[%s]: erase done....arg=0x%x\n", __func__, arg); #endif end: mmc_release_host(host->mmc); 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 cloner_init(struct cloner *cloner) { #ifdef CONFIG_JZ_NAND_MGR if(cloner->args->use_nand_mgr) { nand_probe_burner(&(cloner->args->PartInfo), &(cloner->args->nand_params[0]), cloner->args->nr_nand_args, cloner->args->nand_erase,cloner->args->offsets,cloner->args->nand_erase_count); } #endif /*CONFIG_JZ_NAND_MGR*/ #ifdef CONFIG_MTD_NAND_JZ if(cloner->args->use_nand_mtd) { mtd_nand_probe_burner(&cloner->args->MTDPartInfo, &cloner->args->nand_params, cloner->args->nr_nand_args, cloner->args->nand_erase, &cloner->spl_title, &cloner->spl_title_sz); } #endif /*CONFIG_JZ_NAND_MGR*/ #ifdef CONFIG_JZ_MMC if (cloner->args->use_mmc) { if (cloner->args->mmc_erase) { mmc_erase(cloner); } } #endif /*CONFIG_JZ_MMC*/ #ifdef CONFIG_JZ_SPI #ifdef CONFIG_MTD_SPINAND if(cloner->args->use_spi_nand){ ssi_rate = (&cloner->args->spi_args)->rate; printf("******** ssi_rate = %d oldrate = %d spi_erase = %d\n",ssi_rate,(&cloner->args->spi_args)->rate,cloner->args->spi_erase); get_burner_nandinfo(cloner,&nand_param_from_burner); mtd_spinand_probe_burner(&(cloner->args->spi_erase),&nand_param_from_burner); } #endif if(cloner->args->use_spi_nor){ if (cloner->args->spi_erase == SPI_ERASE_PART) { spi_erase(cloner); } printf("cloner->args->spi_args.rate:%d\n",cloner->args->spi_args.rate); } #endif #if CONFIG_MTD_SFCNAND if(cloner->args->use_sfc_nand){ ssi_rate = (&cloner->args->spi_args)->rate; get_burner_nandinfo(cloner,&nand_param_from_burner); mtd_sfcnand_probe_burner(&(cloner->args->spi_erase),cloner->args->spi_args.sfc_quad_mode,&nand_param_from_burner); } #endif #ifdef CONFIG_JZ_SFC if(cloner->args->use_sfc_nor){ get_norflash_params_from_burner((unsigned char *)cloner->args + sizeof(struct arguments)); if (cloner->args->spi_erase == SPI_ERASE_PART) { sfc_erase(cloner); } printf("cloner->args->spi_args.rate:%d\n",cloner->args->spi_args.rate); } #endif return 0; }
int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong src_addr, dst_addr, size; char *cmd; /*Default Setting to SLOT-0*/ int slot_no = 0, mmc_cont = 0; static used_slots[3] = {0}; if (argc < 2) { goto mmc_cmd_usage; } else if (argc == 2) { if (strncmp(argv[0],"mmcinit",7) !=0) { goto mmc_cmd_usage; } else { slot_no = simple_strtoul(argv[1], NULL, 16); if ((slot_no != 0) && (slot_no != 1)) goto mmc_cmd_usage; if (used_slots[slot_no]==0) { /*Initialized... slot if never initialized*/ used_slots[slot_no]=1; if (mmc_init(slot_no) != 0) { printf("No MMC card found\n"); return 1; } else { mmc_flag[slot_no] = 1; } } } } else { mmc_cont = simple_strtoul(argv[1], NULL, 16); if ((mmc_cont != 0) && (mmc_cont != 1)) goto mmc_cmd_usage; if (!mmc_flag[mmc_cont]) { printf("Try to do init First b4 read/write\n"); goto mmc_cmd_usage; } cmd = argv[2]; if (strcmp(cmd, "erase") == 0) { if (argc != 5) { goto mmc_cmd_usage; } else { src_addr = simple_strtoul(argv[3], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); mmc_erase(mmc_cont, src_addr, size); } } else if (strcmp(cmd, "read") == 0) { if (argc != 6) { goto mmc_cmd_usage; } else { src_addr = simple_strtoul(argv[3], NULL, 16); dst_addr = simple_strtoul(argv[4], NULL, 16); size = simple_strtoul(argv[5], NULL, 16); mmc_read(mmc_cont, src_addr, (unsigned char *)dst_addr, size); } } else if (strcmp(cmd, "write") == 0) { if (argc != 6) { goto mmc_cmd_usage; } else { src_addr = simple_strtoul(argv[3], NULL, 16); dst_addr = simple_strtoul(argv[4], NULL, 16); size = simple_strtoul(argv[5], NULL, 16); mmc_write(mmc_cont, (unsigned char *)src_addr, dst_addr, size); } } else if (strcmp(cmd,"part") == 0) { mmc_part(mmc_cont); } else goto mmc_cmd_usage; } return 0; mmc_cmd_usage: printf("Usage:\n%s\n", cmdtp->usage); return 1; }
int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong src_addr, dst_addr, size; char *cmd; /*Default Setting to SLOT-0*/ int slot_no = 0, mmc_cont = 0; if (argc < 2) { goto mmc_cmd_usage; } else if (argc == 2) { if (strncmp(argv[0], "mmcinit", 7) != 0) { goto mmc_cmd_usage; } else { slot_no = simple_strtoul(argv[1], NULL, 16); if ((slot_no != 0) && (slot_no != 1)) goto mmc_cmd_usage; if (mmc_init(slot_no) != 0) { printf("No MMC card found\n"); return 1; } else { mmc_flag[slot_no] = 1; printf("MMC%d Initalization OK\n", slot_no); } } } else { if ((strncmp(argv[0], "mmc", 3)==0) && (strncmp(argv[1], "init", 4)==0)) { slot_no = simple_strtoul(argv[2], NULL, 16); if ((slot_no != 0) && (slot_no != 1)) goto mmc_cmd_usage; if (mmc_init(slot_no) != 0) { printf("No MMC card found\n"); return 1; } else { mmc_flag[slot_no] = 1; printf("MMC%d Initalization OK\n", slot_no); } return 0; } mmc_cont = simple_strtoul(argv[1], NULL, 16); if ((mmc_cont != 0) && (mmc_cont != 1)) goto mmc_cmd_usage; if (!mmc_flag[mmc_cont]) { printf("Try to do init First b4 read/write\n"); goto mmc_cmd_usage; } cmd = argv[2]; if (strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && strncmp(cmd, "erase", 5) != 0) goto mmc_cmd_usage; if (strcmp(cmd, "erase") == 0) { if (argc != 5) { goto mmc_cmd_usage; } else { src_addr = simple_strtoul(argv[3], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); mmc_erase(mmc_cont, src_addr, size); } } if (strcmp(cmd, "read") == 0) { if (argc != 6) { goto mmc_cmd_usage; } else { dst_addr = simple_strtoul(argv[3], NULL, 16); src_addr = simple_strtoul(argv[4], NULL, 16); size = simple_strtoul(argv[5], NULL, 16); //printf("mmc_cont=%d,src_addr=0x%x,dst_addr=0x%x,size=0x%x\n", mmc_cont,src_addr,dst_addr,size); mmc_read(mmc_cont, src_addr, (unsigned char *)dst_addr, size); } } if (strcmp(cmd, "write") == 0) { if (argc != 6) { goto mmc_cmd_usage; } else { src_addr = simple_strtoul(argv[3], NULL, 16); dst_addr = simple_strtoul(argv[4], NULL, 16); size = simple_strtoul(argv[5], NULL, 16); //printf("mmc_cont=%d,src_addr=0x%x,dst_addr=0x%x,size=0x%x\n", mmc_cont,src_addr,dst_addr,size); mmc_write(mmc_cont, (unsigned char *)src_addr, dst_addr, size); } } } return 0; mmc_cmd_usage: printf("Usage:\n%s\n", cmdtp->usage); return 1; }