v1.0.2 fix fitimage issue

This commit is contained in:
刘可亮
2023-12-22 10:19:53 +08:00
parent 46be2cf5c7
commit 0397775c80
6 changed files with 112 additions and 46 deletions

View File

@@ -64,12 +64,15 @@ static int do_nand_boot(int argc, char *argv[])
info.dev = (void *)mtd;
info.bl_len = mtd->writesize;
info.dev_type = DEVICE_SPINAND;
spl_load_simple_fit(&info, &entry_point);
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;
boot_app((void *)entry_point);
out:
return ret;
}

View File

@@ -63,11 +63,15 @@ static int do_nor_boot(int argc, char *argv[])
info.dev = (void *)mtd;
info.bl_len = 1;
info.dev_type = DEVICE_SPINOR;
spl_load_simple_fit(&info, &entry_point);
ret = spl_load_simple_fit(&info, &entry_point);
if (ret < 0)
goto out;
boot_app((void *)entry_point);
out:
return ret;
}

View File

@@ -78,7 +78,7 @@ static s32 nand_fwc_get_mtd_partitions(struct fwc_info *fwc,
priv->nftl_handler[idx]->nandt->block_start = priv->mtd[idx]->start / priv->mtd[idx]->erasesize;
priv->nftl_handler[idx]->nandt->block_end = (priv->mtd[idx]->start + priv->mtd[idx]->size) / priv->mtd[idx]->erasesize;
for (int offset_e = priv->mtd[idx]->start; offset_e < priv->mtd[idx]->start + priv->mtd[idx]->size;) {
for (int offset_e = 0; offset_e < priv->mtd[idx]->size;) {
mtd_erase(priv->mtd[idx], offset_e, priv->mtd[idx]->erasesize);
offset_e += priv->mtd[idx]->erasesize;
}

View File

@@ -53,13 +53,13 @@ static int mtd_spinand_read_oob(struct mtd_dev *mtd, u32 offset, u8 *data,
flash = (struct aic_spinand *)mtd->priv;
if (offset % flash->info->page_size) {
printf("Offset not aligned with a page (0x%x)\r\n",
pr_err("Offset not aligned with a page (0x%x)\r\n",
flash->info->page_size);
return -1;
}
if ((mtd->size - offset) < flash->info->page_size) {
printf("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
pr_err("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
return -1;
}
@@ -75,6 +75,7 @@ static int mtd_spinand_erase(struct mtd_dev *mtd, u32 offset, u32 len)
u8 err;
u32 start, dolen;
struct aic_spinand *flash;
u32 flash_size = 0;
if (!mtd)
return -1;
@@ -87,6 +88,14 @@ static int mtd_spinand_erase(struct mtd_dev *mtd, u32 offset, u32 len)
if ((mtd->size - offset) < dolen)
dolen = mtd->size - offset;
flash_size = flash->info->page_size * flash->info->pages_per_eraseblock *
flash->info->block_per_lun;
if ((start + dolen) > flash_size) {
pr_err("Erase range 0x%x out of flash capacity 0x%x!\n", start + dolen,
flash_size);
return -1;
}
err = spinand_erase(flash, start, dolen);
return err;
}
@@ -107,12 +116,12 @@ static int mtd_spinand_block_isbad(struct mtd_dev *mtd, u32 offset)
blocksize = flash->info->page_size * flash->info->pages_per_eraseblock;
if (offset % blocksize) {
printf("Offset not aligned with a block (0x%x)\r\n", blocksize);
pr_err("Offset not aligned with a block (0x%x)\r\n", blocksize);
return -1;
}
if ((mtd->size - offset) < blocksize) {
printf("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
pr_err("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
return -1;
}
@@ -121,7 +130,7 @@ static int mtd_spinand_block_isbad(struct mtd_dev *mtd, u32 offset)
err = spinand_block_isbad(flash, blk);
if (err != 0) {
printf("Block %d is bad.\n", blk);
pr_err("Block %d is bad.\n", blk);
}
return err;
}
@@ -142,12 +151,12 @@ static int mtd_spinand_block_markbad(struct mtd_dev *mtd, u32 offset)
blocksize = flash->info->page_size * flash->info->pages_per_eraseblock;
if (offset % blocksize) {
printf("Offset not aligned with a block (0x%x)\r\n", blocksize);
pr_err("Offset not aligned with a block (0x%x)\r\n", blocksize);
return -1;
}
if ((mtd->size - offset) < blocksize) {
printf("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
pr_err("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
return -1;
}
@@ -156,7 +165,7 @@ static int mtd_spinand_block_markbad(struct mtd_dev *mtd, u32 offset)
err = spinand_block_markbad(flash, blk);
if (err != 0) {
printf("Mark badblock %d failed.\n",blk);
pr_err("Mark badblock %d failed.\n", blk);
}
return err;
}
@@ -196,13 +205,13 @@ static int mtd_spinand_write_oob(struct mtd_dev *mtd, u32 offset, u8 *data,
flash = (struct aic_spinand *)mtd->priv;
if (offset % flash->info->page_size) {
printf("Offset not aligned with a page (0x%x)\r\n",
pr_err("Offset not aligned with a page (0x%x)\r\n",
flash->info->page_size);
return -1;
}
if ((mtd->size - offset) < flash->info->page_size) {
printf("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
pr_err("Offset: 0x%x is out of mtd size: 0x%lx.\n", offset, mtd->size);
return -1;
}
@@ -260,7 +269,8 @@ static char *aic_spinand_get_partition_string(struct mtd_dev *mtd)
parts = strdup(parts);
#else
void *res_addr = NULL;
res_addr = aic_get_boot_resource_from_nand(mtd, mtd->writesize, nand_read_data);
res_addr =
aic_get_boot_resource_from_nand(mtd, mtd->writesize, nand_read_data);
parts = private_get_partition_string(res_addr);
if (parts == NULL)
parts = IMAGE_CFG_JSON_PARTS_MTD;
@@ -303,7 +313,7 @@ struct aic_spinand *spinand_probe(u32 spi_bus)
err = spinand_flash_init(flash);
if (err < 0) {
printf("Failed to probe spinand flash.\n");
pr_err("Failed to probe spinand flash.\n");
return NULL;
}

View File

@@ -21,7 +21,7 @@
#undef pr_debug
#ifdef AIC_SPINAND_DRV_DEBUG
#define pr_debug pr_info
#define pr_debug pr_info
#else
#define pr_debug(fmt, ...)
#endif
@@ -34,6 +34,8 @@ struct nand_bbt {
u8 *cache;
};
struct aic_spinand;
/* SPI NAND flash information */
struct aic_spinand_info {
u32 devid;
@@ -44,6 +46,7 @@ struct aic_spinand_info {
u8 is_die_select;
const char *sz_description;
struct spi_nand_cmd_cfg *cmd;
int (*get_status)(struct aic_spinand *flash, u8 status);
};
typedef struct aic_spinand_info *aic_spinand_info_t;
@@ -175,14 +178,15 @@ struct spi_nand_cmd_cfg {
#define CFG_QUAD_ENABLE BIT(0)
/* status register */
#define REG_STATUS 0xc0
#define STATUS_BUSY BIT(0)
#define STATUS_ERASE_FAILED BIT(2)
#define STATUS_PROG_FAILED BIT(3)
#define STATUS_ECC_MASK GENMASK(5, 4)
#define STATUS_ECC_NO_BITFLIPS (0 << 4)
#define STATUS_ECC_HAS_BITFLIPS (1 << 4)
#define STATUS_ECC_UNCOR_ERROR (2 << 4)
#define REG_STATUS 0xc0
#define STATUS_BUSY BIT(0)
#define STATUS_ERASE_FAILED BIT(2)
#define STATUS_PROG_FAILED BIT(3)
#define STATUS_ECC_MASK GENMASK(5, 4)
#define STATUS_ECC_NO_BITFLIPS (0 << 4)
#define STATUS_ECC_HAS_1_4_BITFLIPS (1 << 4)
#define STATUS_ECC_UNCOR_ERROR (2 << 4)
#ifdef SPI_NAND_WINBOND
extern const struct spinand_manufacturer winbond_spinand_manufacturer;

View File

@@ -138,6 +138,27 @@ int spinand_read_cfg(struct aic_spinand *flash, u8 *cfg)
return spinand_read_reg_op(flash, REG_CFG, cfg);
}
int spinand_check_ecc_status(struct aic_spinand *flash, u8 status)
{
if (flash->info->get_status) {
return flash->info->get_status(flash, status);
}
switch (status & STATUS_ECC_MASK) {
case STATUS_ECC_NO_BITFLIPS:
return 0;
case STATUS_ECC_HAS_1_4_BITFLIPS:
return 4;
case STATUS_ECC_UNCOR_ERROR:
return -SPINAND_ERR_ECC;
default:
break;
}
return -SPINAND_ERR;
}
int spinand_isbusy(struct aic_spinand *flash, u8 *status)
{
u8 SR = 0xFF;
@@ -495,11 +516,13 @@ int spinand_read_page(struct aic_spinand *flash, u32 page, u8 *data,
goto exit_spinand_read_page;
}
status = (status & 0x30) >> 4;
if ((status > 0x01)) {
result = -SPINAND_ERR_ECC;
result = spinand_check_ecc_status(flash, status);
if (result < 0) {
pr_err("Error ECC status error[0x%x].\n", status);
goto exit_spinand_read_page;
} else if (result > 0) {
pr_debug("with %d bit/page ECC corrections, status : [0x%x].\n", result,
status);
}
if (data && data_len) {
@@ -658,11 +681,14 @@ int spinand_continuous_read(struct aic_spinand *flash, u32 page, u8 *data,
goto exit_spinand_continuous_read;
}
status = (status & 0x30) >> 4;
if ((status > 0x01)) {
result = spinand_check_ecc_status(flash, status);
if (result < 0) {
result = -SPINAND_ERR_ECC;
pr_err("Error ECC status error[0x%x].\n", status);
goto exit_spinand_continuous_read;
} else if (result > 0) {
pr_debug("with %d bit/page ECC corrections, status : [0x%x].\n", result,
status);
}
result = spinand_read_from_cache_cont_op(flash, data, size);
@@ -760,11 +786,13 @@ int spinand_write_page(struct aic_spinand *flash, u32 page, const u8 *data,
goto exit_spinand_write_page;
}
status = (status & 0x30) >> 4;
if ((status > 0x01)) {
result = -SPINAND_ERR_ECC;
result = spinand_check_ecc_status(flash, status);
if (result < 0) {
pr_err("Error ECC status error[0x%x].\n", status);
goto exit_spinand_write_page;
} else if (result > 0) {
pr_debug("with %d bit/page ECC corrections, status : [0x%x].\n", result,
status);
}
result = SPINAND_SUCCESS;
@@ -796,27 +824,25 @@ int spinand_block_markbad(struct aic_spinand *flash, u16 blk)
return spinand_write_page(flash, page, NULL, 0, &badblockmarker, 1);
}
#define READ_DATE_OFFSET_ALIGN 1
#define READ_DATE_OFFSET_UNALIGN 2
int spinand_read(struct aic_spinand *flash, u8 *addr, u32 offset, u32 size)
{
int err = 0;
u32 page, cplen;
u32 off = offset;
u8 *buf = NULL, *p, copy_flag;
u8 *buf = NULL, *p, copy_flag = 0;
u32 remaining = size;
u16 blk;
u32 blk_size;
u32 off_in_page = 0;
if (!flash) {
pr_err("flash is NULL\r\n");
return -SPINAND_ERR;
}
if (offset % flash->info->page_size) {
pr_err("Offset not aligned with a page (0x%x)\r\n",
flash->info->page_size);
return -SPINAND_ERR;
}
buf = malloc(flash->info->page_size + flash->info->oob_size);
if (!buf) {
pr_err("Failed to malloc spinand buf.\n");
@@ -835,12 +861,19 @@ int spinand_read(struct aic_spinand *flash, u8 *addr, u32 offset, u32 size)
}
while (remaining > 0) {
if (remaining >= flash->info->page_size) {
p = addr;
copy_flag = 0;
if (off % flash->info->page_size == 0) {
if (remaining >= flash->info->page_size) {
p = addr;
copy_flag = 0;
} else {
p = buf;
copy_flag = READ_DATE_OFFSET_UNALIGN;
memset(buf, 0xFF, flash->info->page_size);
}
} else {
p = buf;
copy_flag = 1;
copy_flag = READ_DATE_OFFSET_ALIGN;
memset(buf, 0xFF, flash->info->page_size);
}
page = off / flash->info->page_size;
@@ -850,10 +883,22 @@ int spinand_read(struct aic_spinand *flash, u8 *addr, u32 offset, u32 size)
goto exit_spinand_read;
cplen = flash->info->page_size;
if (remaining < cplen)
if (copy_flag == READ_DATE_OFFSET_ALIGN) {
/*Misaligned offset with page address*/
off_in_page = off % flash->info->page_size;
if (remaining <= flash->info->page_size - off_in_page) {
cplen = remaining;
} else {
cplen = flash->info->page_size - off_in_page;
}
memcpy(addr, buf + off_in_page, cplen);
} else if (copy_flag == READ_DATE_OFFSET_UNALIGN) {
/*Align offset with page address*/
cplen = remaining;
if (copy_flag)
memcpy(addr, buf, cplen);
}
remaining -= cplen;
off += cplen;
addr += cplen;