Files
gk-sdk/source/bootloader/u-boot-2020.01/lotus/flash_api/flash_read.c
T

166 lines
3.8 KiB
C
Executable File

/*
* Copyright (c) LOTUS. All rights reserved.
*/
#include <linux/lotus/flash_read.h>
#include <common.h>
#if defined (CONFIG_FMC_SPI_NOR)
#include <spi_flash.h>
#endif
#if defined (CONFIG_FMC_SPI_NAND)
#include <nand.h>
#endif
#if defined(CONFIG_SUPPORT_EMMC_BOOT)
#include <mmc.h>
#endif
/*
* read from spi nor flash by offset and size.
*/
#if defined (CONFIG_FMC_SPI_NOR)
static int read_flash_spi(unsigned long offset, unsigned int size, unsigned char *addr)
{
/* init env_flash */
struct spi_flash *env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
if (env_flash == NULL) {
printf("read_flash_spi spi_flash_probe failed\n");
return -1;
}
/* read flash */
int ret = spi_flash_read(env_flash, offset, size, addr);
if (ret != 0) {
printf("read_flash_spi spi_flash_read failed\n");
goto EXIT_FAILURE;
}
EXIT_FAILURE:
spi_flash_free(env_flash);
return ret;
}
#else
static int read_flash_spi(unsigned long offset, unsigned int size, unsigned char *addr)
{
printf("Error: read_flash_spi not define CONFIG_CMD_SF\n");
return -1;
}
#endif
/*
* read from nand flash by offset and size.
*/
#if defined (CONFIG_FMC_SPI_NAND)
static int read_flash_nand(unsigned long offset, unsigned int size, unsigned char *addr)
{
struct mtd_info *mtd;
size_t rwsize = size;
size_t block_size;
int ret;
mtd = nand_info[0];
if (mtd == NULL) {
printf("read_flash_nand mtd == NULL\n");
return -1;
}
block_size = mtd->erasesize;
if (nand_block_isbad(mtd, offset))
offset += block_size;
ret = nand_read_skip_bad(mtd, offset, &rwsize, NULL, mtd->size, addr);
return ret;
}
#else
static int read_flash_nand(unsigned long offset, unsigned int size, unsigned char *addr)
{
printf("Error: read_flash_nand not define CONFIG_CMD_NAND\n");
return -1;
}
#endif
/*
* read from emmc flash by offset and size.
*/
#if defined (CONFIG_SUPPORT_EMMC_BOOT)
static int read_flash_mmc(unsigned long offset, unsigned int size, unsigned char *addr)
{
struct mmc *mmc = find_mmc_device(0);
if (mmc == NULL) {
printf("read_flash_mmc find_mmc_device failed\n");
return -1;
}
lbaint_t blks;
if ((size % MMC_MAX_BLOCK_LEN) != 0)
blks = size / MMC_MAX_BLOCK_LEN + 1;
else
blks = size / MMC_MAX_BLOCK_LEN;
ulong blks_read = blk_dread(mmc_get_blk_desc(mmc), (offset / MMC_MAX_BLOCK_LEN), blks, (void *)addr);
if (blks_read != blks) {
printf("mmc blk read failed:%lu.\n", blks_read);
return -1;
}
return 0;
}
#else
static int read_flash_mmc(unsigned long offset, unsigned int size, unsigned char *addr)
{
printf("Error: read_flash_mmc not define CONFIG_CMD_NAND\n");
return -1;
}
#endif
/*
* read flash into out_addr from offset.
*/
int flash_read(unsigned long offset, unsigned int size, unsigned char *out_addr)
{
if ((offset % FLASH_ALIGNED_SIZE) != 0) {
printf("offset(0x%lx) should aligned with %d.\n", offset, FLASH_ALIGNED_SIZE);
return -1;
}
if (out_addr == NULL) {
return -1;
}
int (*read_flash_choose)(unsigned long offset, unsigned int size, unsigned char* addr) = NULL;
switch (get_boot_media()) {
case BOOT_MEDIA_EMMC:
read_flash_choose = read_flash_mmc;
break;
case BOOT_MEDIA_NAND:
read_flash_choose = read_flash_nand;
break;
case BOOT_MEDIA_SPIFLASH:
read_flash_choose = read_flash_spi;
break;
default:
break;
}
if (read_flash_choose == NULL) {
printf("flash_read not found flash type!\n");
return -1;
}
return read_flash_choose(offset, size, out_addr);
}
int flash_read_aligned(unsigned long offset, unsigned int size, unsigned char *out_addr)
{
if (out_addr == NULL) {
printf("out_addr is null.\n");
return -1;
}
if ((size % FLASH_ALIGNED_SIZE) != 0) {
printf("size should aligned with %d.\n", FLASH_ALIGNED_SIZE);
return -1;
}
return flash_read(offset, size, out_addr);
}