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