[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/loader/drivers/bbt.c b/boot/common/src/loader/drivers/bbt.c
new file mode 100755
index 0000000..bf46266
--- /dev/null
+++ b/boot/common/src/loader/drivers/bbt.c
@@ -0,0 +1,250 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+
+
+#include <common.h>
+#include <asm/io.h>
+#include <bbt.h>
+#include "config.h"
+#include "flash.h"
+
+
+static uint8_t block_bad_table[BBT_SIZE]={0};
+
+
+static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+ .offs = 4,
+ .len = 4,
+ .veroffs = 20,
+ .maxblocks = 16,
+ .pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+ .offs = 4,
+ .len = 4,
+ .veroffs = 20,
+ .maxblocks = 16,
+ .pattern = mirror_pattern,
+};
+
+static int nand_check_pattern(uint8_t *buf,struct nand_bbt_descr *td)
+{
+ int i;
+ uint8_t *p = buf;
+ p += td->offs;
+
+ /* Compare the pattern */
+ for (i = 0; i < td->len; i++)
+ {
+ if (p[i] != td->pattern[i])
+ return -1;
+ }
+
+ return 0;
+}
+
+void nand_creat_ram_bbt( void )
+{
+ uint32_t i = 0;
+ uint32_t off = 0;
+ uint32_t oob_size = flash.oob_size;
+ uint32_t block_size = flash.block_size;
+ uint8_t oob[256]; /* ÕâÀﶨÒå×î´óµÄOOB SIZE */
+//#ifdef CONFIG_ZX297520V3E_MDL_AB
+#if defined(CONFIG_ZX297520V3E_MDL_AB) || defined(CONFIG_ZX297520V3E_VEHICLE_DC)
+ uint32_t block_nums = 72;
+#else
+ uint32_t block_nums = 17;
+#endif
+
+ for( i=0; i<block_nums; i++ )
+ {
+ flash.read_oob(&oob[0], off, oob_size);
+ if(oob[0] != 0xff) /* bad block */
+ block_bad_table[i] = BAD_BLOCK;
+ else
+ block_bad_table[i] = 0x0;
+
+ off += block_size;
+ }
+}
+
+
+int nand_search_bbt(struct nand_bbt_descr *td)
+{
+
+ int startblock, block;
+ int blocktopage = flash.block_size_shift - flash.page_size_shift;
+
+ uint8_t oob_buffer[256]={0xFF};
+ uint32_t offs = 0;
+
+ /* Search direction down -> top */
+ startblock = flash.block_num -1;
+
+ td->page= -1;
+ /* Scan the maximum number of blocks */
+ for (block = 0; block < td->maxblocks; block++)
+ {
+
+ int actblock = startblock -block;
+ offs = actblock << flash.block_size_shift;
+
+ /* Read first page */
+ flash.read_oob(oob_buffer, offs, flash.oob_size);
+ if (!nand_check_pattern(oob_buffer,td))
+ {
+ td->page = actblock << blocktopage;
+ td->version= oob_buffer[td->veroffs];
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static int nand_read_bbt(struct nand_bbt_descr *td,int num)
+{
+ int bits=2;
+
+ int res, i, j, act = 0;
+ int totlen;
+ int from;
+ uint8_t msk = (uint8_t) ((1 << bits) - 1);
+ totlen = (num * bits) >> 3;
+ from =(td->page)<<(flash.page_size_shift);
+ char* buf;
+
+
+ res = flash.read_page_raw(CFG_TEMP_ADDR, from);
+ if (res < 0)
+ {
+ return -1;
+ }
+
+ buf =(char*) CFG_TEMP_ADDR;
+
+
+ /* Analyse data */
+ for (i = 0; i < totlen; i++)
+ {
+ uint8_t dat = buf[i];
+ for (j = 0; j < 8; j += bits, act += 2)
+ {
+ uint8_t tmp = (dat >> j) & msk;
+ if (tmp == msk)
+ {
+ block_bad_table[(act >> 1)]= 0X0;
+ continue;
+ }
+ else
+ {
+ block_bad_table[(act >> 1)]= BAD_BLOCK;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static void nand_init_bbt_descr(struct nand_bbt_descr *td,
+ struct nand_bbt_descr *md)
+{
+ switch(flash.manuf_id)
+ {
+ case NAND_MFR_PARAGON:
+ if(flash.device_id != NAND_DEVID_FDANWEI_1G)
+ {
+ td->offs = BBT_INFO_OOB_OFFSET_PARAGON;
+ md->offs = BBT_INFO_OOB_OFFSET_PARAGON;
+ td->veroffs = BBT_INFO_OOB_VER_OFFSET_PARAGON;
+ md->veroffs = BBT_INFO_OOB_VER_OFFSET_PARAGON;
+ }
+ break;
+ case NAND_MFR_HEYANGTEK:
+ td->offs = BBT_INFO_OOB_OFFSET_HEYANGTEK;
+ md->offs = BBT_INFO_OOB_OFFSET_HEYANGTEK;
+ td->veroffs = BBT_INFO_OOB_VER_OFFSET_HEYANGTEK;
+ md->veroffs =BBT_INFO_OOB_VER_OFFSET_HEYANGTEK;
+ break;
+ default:
+ break;
+ }
+}
+
+int nand_creat_bbt( void )
+{
+ struct nand_bbt_descr *td = &bbt_main_descr;
+ struct nand_bbt_descr *md = &bbt_mirror_descr;
+
+ nand_init_bbt_descr(td, md);
+
+ // 2.0 search main bbt
+ nand_search_bbt(td);
+ // 2.1 search mirror bbt
+ nand_search_bbt(md);
+
+ if(td->page==-1&&md->page ==-1)
+ {
+ /* if failed found bbt, we create a ram bbt */
+ nand_creat_ram_bbt();
+ return 0;
+ }
+
+ // 3.0 read and analyze bbt
+ if(td->page==-1)
+ {
+ nand_read_bbt(md,BBT_SIZE);
+ }
+ else
+ {
+ if(md->page == -1)
+ {
+ nand_read_bbt(td,BBT_SIZE);
+ }
+ else
+ {
+ if(td->version >= md->version)
+ {
+ nand_read_bbt(td,BBT_SIZE);
+ }
+ else
+ {
+ nand_read_bbt(md,BBT_SIZE);
+ }
+ }
+ }
+ printf("bbt ok.\n");
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Function:
+ * Description:
+ * Parameters:
+ * Input:
+ *
+ * Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+uint32_t nand_block_isbad(uint32_t offset)
+{
+ uint32_t block_offset = offset >> (flash.block_size_shift);
+ return block_bad_table[block_offset];
+}
+
+
+