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