Beispiel #1
0
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;
}
Beispiel #5
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;
}
Beispiel #6
0
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;
}
Beispiel #8
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;

	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;
}