rockchip: vendor: Support MTD SPI Nor

Change-Id: I67d01db2d335abfd483596a2f7033d1e38cffaf5
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin 2020-12-22 20:48:24 +08:00 committed by Jianhong Chen
parent 9ff9a8fead
commit 1e5036b9d9
1 changed files with 47 additions and 45 deletions

View File

@ -85,14 +85,13 @@ struct vendor_info {
u32 *version2;
};
struct mtd_nand_info {
struct mtd_flash_info {
u32 part_offset;
u32 part_size;
u32 blk_offset;
u32 page_offset;
u32 version;
u32 ops_size;
u32 page_size;
u32 blk_size;
};
@ -129,7 +128,7 @@ static struct vendor_info vendor_info;
static int bootdev_type;
#ifdef CONFIG_MTD_BLK
static struct mtd_nand_info nand_info;
static struct mtd_flash_info s_flash_info;
static const char *vendor_mtd_name = "vnvm";
#endif
@ -175,48 +174,49 @@ static int mtd_vendor_storage_init(struct blk_desc *dev_desc)
if (part_num < 0)
return -EIO;
nand_info.part_offset = (u32)vnvm_part_info.start;
nand_info.part_size = (u32)vnvm_part_info.size;
nand_info.page_offset = 0;
nand_info.blk_offset = 0;
nand_info.version = 0;
nand_info.page_size = mtd->writesize >> 9;
nand_info.blk_size = mtd->erasesize >> 9;
nand_info.ops_size = (FLASH_VENDOR_INFO_SIZE + mtd->writesize - 1) /
mtd->writesize;
nand_info.ops_size *= nand_info.page_size;
s_flash_info.part_offset = (u32)vnvm_part_info.start;
s_flash_info.part_size = (u32)vnvm_part_info.size;
s_flash_info.page_offset = 0;
s_flash_info.blk_offset = 0;
s_flash_info.version = 0;
/* SPI Nor unified to Support 64KB erase block */
if (dev_desc->devnum == BLK_MTD_SPI_NOR)
s_flash_info.blk_size = 0x80;
else
s_flash_info.blk_size = mtd->erasesize >> 9;
s_flash_info.ops_size = roundup(FLASH_VENDOR_INFO_SIZE, mtd->writesize) >> 9;
/* scan bad block and calculate the real size can be used */
bad_block_size = 0;
for (offset = 0; offset < nand_info.part_size; offset += nand_info.blk_size) {
if (mtd_block_isbad(mtd, (nand_info.part_offset + offset) << 9))
bad_block_size += nand_info.blk_size;
for (offset = 0; offset < s_flash_info.part_size; offset += s_flash_info.blk_size) {
if (mtd_block_isbad(mtd, (s_flash_info.part_offset + offset) << 9))
bad_block_size += s_flash_info.blk_size;
}
nand_info.part_size -= bad_block_size;
s_flash_info.part_size -= bad_block_size;
for (offset = 0; offset < nand_info.part_size; offset += nand_info.blk_size) {
ret = blk_dread(dev_desc, nand_info.part_offset + offset,
for (offset = 0; offset < s_flash_info.part_size; offset += s_flash_info.blk_size) {
ret = blk_dread(dev_desc, s_flash_info.part_offset + offset,
FLASH_VENDOR_INFO_SIZE >> 9,
(u8 *)buf);
debug("%s: read %x version = %x\n", __func__,
nand_info.part_offset + offset,
s_flash_info.part_offset + offset,
vendor_info.hdr->version);
if (ret == (FLASH_VENDOR_INFO_SIZE >> 9) && vendor_info.hdr->tag == VENDOR_TAG &&
vendor_info.hdr->version == *vendor_info.version2) {
if (vendor_info.hdr->version > nand_info.version) {
nand_info.version = vendor_info.hdr->version;
nand_info.blk_offset = offset;
if (vendor_info.hdr->version > s_flash_info.version) {
s_flash_info.version = vendor_info.hdr->version;
s_flash_info.blk_offset = offset;
}
}
}
debug("%s: nand_info.version = %x %x\n", __func__, nand_info.version, nand_info.blk_offset);
if (nand_info.version) {
for (offset = nand_info.blk_size - nand_info.ops_size;
debug("%s: s_flash_info.version = %x %x\n", __func__, s_flash_info.version, s_flash_info.blk_offset);
if (s_flash_info.version) {
for (offset = s_flash_info.blk_size - s_flash_info.ops_size;
offset >= 0;
offset -= nand_info.ops_size) {
ret = blk_dread(dev_desc, nand_info.part_offset +
nand_info.blk_offset + offset,
offset -= s_flash_info.ops_size) {
ret = blk_dread(dev_desc, s_flash_info.part_offset +
s_flash_info.blk_offset + offset,
1,
(u8 *)buf);
@ -225,22 +225,22 @@ static int mtd_vendor_storage_init(struct blk_desc *dev_desc)
continue;
/* point to the last programed page */
if (nand_info.page_offset < offset)
nand_info.page_offset = offset;
if (s_flash_info.page_offset < offset)
s_flash_info.page_offset = offset;
if (ret != 1 || vendor_info.hdr->tag != VENDOR_TAG)
continue;
ret = blk_dread(dev_desc, nand_info.part_offset +
nand_info.blk_offset + offset,
ret = blk_dread(dev_desc, s_flash_info.part_offset +
s_flash_info.blk_offset + offset,
FLASH_VENDOR_INFO_SIZE >> 9,
(u8 *)buf);
debug("%s: read %x version = %x\n", __func__,
nand_info.part_offset + nand_info.blk_offset + offset,
s_flash_info.part_offset + s_flash_info.blk_offset + offset,
vendor_info.hdr->version);
if (ret == (FLASH_VENDOR_INFO_SIZE >> 9) && vendor_info.hdr->tag == VENDOR_TAG &&
vendor_info.hdr->version == *vendor_info.version2) {
nand_info.version = vendor_info.hdr->version;
s_flash_info.version = vendor_info.hdr->version;
break;
}
}
@ -265,21 +265,23 @@ static int mtd_vendor_write(struct blk_desc *dev_desc,
int ret, count = 0, err = 0;
re_write:
debug("[Vendor INFO]:%s page_offset=0x%x count = %x\n", __func__, nand_info.part_offset +
nand_info.blk_offset + nand_info.page_offset, count);
if (nand_info.page_offset >= nand_info.blk_size) {
nand_info.blk_offset += nand_info.blk_size;
if (nand_info.blk_offset >= nand_info.part_size)
nand_info.blk_offset = 0;
nand_info.page_offset = 0;
debug("[Vendor INFO]:%s page_offset=0x%x count = %x\n", __func__, s_flash_info.part_offset +
s_flash_info.blk_offset + s_flash_info.page_offset, count);
if (s_flash_info.page_offset >= s_flash_info.blk_size) {
s_flash_info.blk_offset += s_flash_info.blk_size;
if (s_flash_info.blk_offset >= s_flash_info.part_size)
s_flash_info.blk_offset = 0;
s_flash_info.page_offset = 0;
}
ret = blk_dwrite(dev_desc, nand_info.part_offset +
nand_info.blk_offset + nand_info.page_offset,
dev_desc->op_flag |= BLK_MTD_CONT_WRITE;
ret = blk_dwrite(dev_desc, s_flash_info.part_offset +
s_flash_info.blk_offset + s_flash_info.page_offset,
FLASH_VENDOR_INFO_SIZE >> 9,
(u8 *)buf);
dev_desc->op_flag &= ~(BLK_MTD_CONT_WRITE);
nand_info.page_offset += nand_info.ops_size;
s_flash_info.page_offset += s_flash_info.ops_size;
if (ret != (FLASH_VENDOR_INFO_SIZE >> 9)) {
err++;
if (err > 3)