/* * Function: mmc_read * Arg : Data address on card, o/p buffer & data length * Return : 0 on Success, non zero on failure * Flow : Read data from the card to out */ uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len) { uint32_t ret = 0; uint32_t block_size; uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ; void *dev; uint8_t *sptr = (uint8_t *)out; dev = target_mmc_device(); block_size = mmc_get_device_blocksize(); ASSERT(!(data_addr % block_size)); ASSERT(!(data_len % block_size)); /* * dma onto write back memory is unsafe/nonportable, * but callers to this routine normally provide * write back buffers. Invalidate cache * before read data from mmc. */ arch_clean_invalidate_cache_range((addr_t)(out), 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 > read_size) { ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size)); if (ret) { dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size)); return ret; } sptr += read_size; data_addr += read_size; data_len -= read_size; } if (data_len) ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size)); if (ret) dprintf(CRITICAL, "Failed Reading block @ %x\n",(unsigned int) (data_addr / block_size)); } else { ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size)); if (ret) { dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr); } arch_invalidate_cache_range((addr_t)out, data_len); } return ret; }
/* * Function: mmc_read * Arg : Data address on card, o/p buffer & data length * Return : 0 on Success, non zero on failure * Flow : Read data from the card to out */ uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len) { uint32_t ret = 0; uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ; struct mmc_device *dev; uint8_t *sptr = (uint8_t *)out; ASSERT(!(data_addr % MMC_BLK_SZ)); ASSERT(!(data_len % MMC_BLK_SZ)); dev = 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 > read_size) { ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ)); if (ret) { dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ)); return ret; } sptr += read_size; data_addr += read_size; data_len -= read_size; } if (data_len) ret = mmc_sdhci_read(dev, (void *)sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ)); if (ret) dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / MMC_BLK_SZ)); return ret; }