static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks) { uint32_t *out; uint32_t block_size = mmc_get_device_blocksize(); uint32_t erase_size = (block_size * num_blks); uint32_t scratch_size = target_get_max_flash_size(); dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks); if (erase_size <= scratch_size) { /* Use scratch address if the unaligned blocks */ out = (uint32_t *) target_get_scratch_address(); } else { dprintf(CRITICAL, "Erase Fail: Erase size: %u is bigger than scratch region\n", scratch_size); return 1; } memset((void *)out, 0, erase_size); /* Flush the data to memory before writing to storage */ arch_clean_invalidate_cache_range((addr_t) out , erase_size); if (mmc_sdhci_write(dev, out, blk_addr, num_blks)) { dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr); return 1; } return 0; }
/* * Function: mmc_write * Arg : Data address on card, data length, i/p buffer * Return : 0 on Success, non zero on failure * Flow : Write the data from in to the card */ uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in) { uint32_t val = 0; uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ; uint8_t *sptr = (uint8_t *)in; struct mmc_device *dev; dev = target_mmc_device(); ASSERT(!(data_addr % MMC_BLK_SZ)); if (data_len % MMC_BLK_SZ) data_len = ROUNDUP(data_len, MMC_BLK_SZ); /* TODO: This function is aware of max data that can be * tranferred using sdhci adma mode, need to have a cleaner * implementation to keep this function independent of sdhci * limitations */ while (data_len > write_size) { val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ)); if (val) { dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ)); return val; } sptr += write_size; data_addr += write_size; data_len -= write_size; } if (data_len) val = mmc_sdhci_write(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ)); if (val) dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / MMC_BLK_SZ)); return val; }
/* * Function: mmc_write * Arg : Data address on card, data length, i/p buffer * Return : 0 on Success, non zero on failure * Flow : Write the data from in to the card */ uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in) { uint32_t val = 0; int ret = 0; uint32_t block_size = 0; uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ; uint8_t *sptr = (uint8_t *)in; void *dev; dev = target_mmc_device(); block_size = mmc_get_device_blocksize(); ASSERT(!(data_addr % block_size)); if (data_len % block_size) data_len = ROUNDUP(data_len, block_size); /* * Flush the cache before handing over the data to * storage driver */ arch_clean_invalidate_cache_range((addr_t)in, data_len); if (target_mmc_device()) { /* TODO: This function is aware of max data that can be * tranferred using sdhci adma mode, need to have a cleaner * implementation to keep this function independent of sdhci * limitations */ while (data_len > write_size) { val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size)); if (val) { dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size)); return val; } sptr += write_size; data_addr += write_size; data_len -= write_size; } if (data_len) val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size)); if (val) dprintf(CRITICAL, "Failed Writing block @ %x\n",(unsigned int)(data_addr / block_size)); } else { ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size)); if (ret) { dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr); val = 1; } } return val; }