static int mmc_samsung_smart_read(struct mmc_card *card, u8 *rdblock) 
{ 
    int err, errx=0; 

    /* enter vendor Smart Report mode */ 
    err = mmc_movi_vendor_cmd(card, 0xEFAC62EC); 
    if (err) 
    { 
        pr_err("Failed entering Smart Report mode(1, %d)\n", err); 
        return err; 
    } 
    err = mmc_movi_vendor_cmd(card, 0x0000CCEE); 
    if (err) { 
        pr_err("Failed entering Smart Report mode(2, %d)\n", err); 
        return err; 
    } 
    /* read Smart Report */ 
    err = mmc_movi_read_cmd(card, rdblock); 
    if (err) 
        pr_err("Failed reading Smart Report(%d)\n", err); 
    
    /* Do NOT return yet; we must leave Smart Report mode.*/ 
    /* exit vendor Smart Report mode */ 
    errx = mmc_movi_vendor_cmd(card, 0xEFAC62EC); 
    if (errx) 
        pr_err("Failed exiting Smart Report mode(1, %d)\n", errx); 
    else { 
        errx = mmc_movi_vendor_cmd(card, 0x00DECCEE); 
        if (errx) 
            pr_err("Failed exiting Smart Report mode(2, %d)\n",errx); 
    } 
    if (err) 
        return err; 
    return errx; 
} 
Пример #2
0
int mmc_movi_read_ram_page(struct mmc_card *card, u8 *buffer, u32 address)
{
	int err = 0, errx = 0;
	u32 val;

	mmc_claim_host(card->host);

	/* enter vendor mode for RAM reading */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x10210002);
	if (err)
		goto out;

	/* In the current mode, erase command sets RAM address to read. */
	err = mmc_movi_erase_cmd(card, cpu_to_le32(address), 512);
	if (err) {
		pr_err("%s: Failed to set read address\n",
				mmc_hostname(card->host));
		goto err_check_patch;
	}

	err = mmc_movi_read_cmd(card, (u8 *)buffer, 0, 1);
	if (err) {
		pr_err("%s: Failed to read patch\n",
				mmc_hostname(card->host));
		goto err_check_patch;
	}

err_check_patch:
	/* exit vendor cmd mode */
	errx = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (errx)
		goto out;

	errx = mmc_movi_vendor_cmd(card, 0x00DECCEE);
	if (errx || err)
		goto out;

out:
	mmc_release_host(card->host);
	return err;
}
Пример #3
0
static int mmc_movi_sds_patch(struct mmc_card *card)
{
	int err = 0, errx = 0;
	void *buffer;
	unsigned i;
	static const struct {
		u32 address;
		u32 value;
	} patches[] = {
		/* write the new function to the RAM */
		{ 0x00040300, 0x4A03B510 },
		{ 0x00040304, 0x28004790 },
		{ 0x00040308, 0xE7FED100 },
		{ 0x0004030C, 0x0000BD10 },
		{ 0x00040310, 0x00059D73 },
		/* patch the old call to call the new function */
		{ 0x0005C7EA, 0xFD89F7E3 },
	};
	pr_info("%s: Fixing MoviNAND SDS bug.\n", mmc_hostname(card->host));

	buffer = kmalloc(512, GFP_KERNEL);
	if (!buffer) {
		pr_err("%s: kmalloc failed.\n", __func__);
		return -ENOMEM;
	}

	/* enter vendor mode for RAM patching */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x10210000);
	if (err)
		goto out;

	/* In the current mode, erase command modifies RAM. */
	for (i = 0; i < ARRAY_SIZE(patches); i++) {
		err = mmc_movi_erase_cmd(card, patches[i].address,
		                         cpu_to_le32(patches[i].value));
		if (err) {
			pr_err("%s: Patch %u failed\n",
			       mmc_hostname(card->host), i);
			goto err_patch;
		}
	}

err_patch:
	/* exit vendor command mode */
	errx = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (errx)
		goto out;

	errx = mmc_movi_vendor_cmd(card, 0x00DECCEE);
	if (errx || err)
		goto out;

	/* verify the written patch */
	pr_info("%s: Verifying SDS patch.\n", mmc_hostname(card->host));

	/* enter vendor mode for RAM reading */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x10210002);
	if (err)
		goto out;

	/* In the current mode, erase command sets RAM address to read. */
	for (i = 0; i < ARRAY_SIZE(patches); i++) {
		err = mmc_movi_erase_cmd(card, patches[i].address, 4);
		if (err) {
			pr_err("%s: Failed to set read address for patch %u\n",
			       mmc_hostname(card->host), i);
			goto err_check_patch;
		}

		err = mmc_movi_read_cmd(card, (u8 *)buffer, 0, 1);
		if (err) {
			pr_err("%s: Failed to read patch %u\n",
			       mmc_hostname(card->host), i);
			goto err_check_patch;
		}

		if (cpu_to_le32(*(u32 *)buffer) != patches[i].value) {
			pr_err("%s: Patch %u verification failed\n",
			       mmc_hostname(card->host), i);
			goto err_check_patch;
		}
	}

err_check_patch:
	/* exit vendor cmd mode */
	errx = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (errx)
		goto out;

	errx = mmc_movi_vendor_cmd(card, 0x00DECCEE);
	if (errx || err)
		goto out;

out:
	kfree(buffer);
	if (err)
		return err;
	return errx;
}
/*
 * Copy entire page when wear leveling is happened
 */
static int mmc_set_wearlevel_page(struct mmc_card *card)
{
	int err;
#ifdef TEST_MMC_FW_PATCHING
	void *buffer;
	buffer = kmalloc(512, GFP_KERNEL);
	if (!buffer) {
		pr_err("Fail to alloc memory for set wearlevel\n");
		return -ENOMEM;
	}
#endif /* TEST_MMC_FW_PATCHING */

	/* modification vendor cmd */
	/* enter vendor command mode */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x10210000);
	if (err)
		goto out;

	/* set value 0x000000FF : It's hidden data
	 * When in vendor command mode, the erase command is used to
	 * patch the firmware in the internal sram.
	 */
	err = mmc_movi_erase_cmd(card, 0x0004DD9C, 0x000000FF);
	if (err) {
		pr_err("Fail to Set WL value1\n");
		goto err_set_wl;
	}

	/* set value 0xD20228FF : It's hidden data */
	err = mmc_movi_erase_cmd(card, 0x000379A4, 0xD20228FF);
	if (err) {
		pr_err("Fail to Set WL value2\n");
		goto err_set_wl;
	}

err_set_wl:
	/* exit vendor command mode */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x00DECCEE);
	if (err)
		goto out;

#ifdef TEST_MMC_FW_PATCHING
	/* read and verify vendor cmd */
	/* enter vendor cmd */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x10210002);
	if (err)
		goto out;

	err = mmc_movi_erase_cmd(card, 0x0004DD9C, 0x00000004);
	if (err) {
		pr_err("Fail to Check WL value1\n");
		goto err_check_wl;
	}

	mmc_movi_read_cmd(card, (u8 *)buffer);
	pr_debug("buffer[0] is 0x%x\n", *(u8 *)buffer);

	err = mmc_movi_erase_cmd(card, 0x000379A4, 0x00000004);
	if (err) {
		pr_err("Fail to Check WL value2\n");
		goto err_check_wl;
	}

	mmc_movi_read_cmd(card, (u8 *)buffer);
	pr_debug("buffer[0] is 0x%x\n", *(u8 *)buffer);

err_check_wl:
	/* exit vendor cmd mode */
	err = mmc_movi_vendor_cmd(card, 0xEFAC62EC);
	if (err)
		goto out;

	err = mmc_movi_vendor_cmd(card, 0x00DECCEE);
	if (err)
		goto out;

#endif /* TEST_MMC_FW_PATCHING */

 out:
#ifdef TEST_MMC_FW_PATCHING
	kfree(buffer);
#endif /* TEST_MMC_FW_PATCHING */
	return err;
}