diff --git a/drivers/rkflash/flash_com.h b/drivers/rkflash/flash_com.h index b60875d382..8c23d1fd2b 100644 --- a/drivers/rkflash/flash_com.h +++ b/drivers/rkflash/flash_com.h @@ -19,8 +19,8 @@ #define NAND_IDB_START 64 /* 32 KB*/ #define NAND_IDB_SIZE 512 /* 256 KB*/ -#define NAND_IDB_END NAND_IDB_START + NAND_IDB_SIZE - 1 -#define DEFAULT_IDB_RESERVED_BLOCK 16 +#define NAND_IDB_END (NAND_IDB_START + NAND_IDB_SIZE - 1) +#define DEFAULT_IDB_RESERVED_BLOCK 8 #define FULL_SLC 0 #define SLC 1 diff --git a/drivers/rkflash/sfc.h b/drivers/rkflash/sfc.h index bcbbcc3a9f..a5c6b10c51 100644 --- a/drivers/rkflash/sfc.h +++ b/drivers/rkflash/sfc.h @@ -189,6 +189,21 @@ struct rk_sfc_op { union SFCCTRL_DATA sfctrl; }; +#define IDB_BLOCK_TAG_ID 0xFCDC8C3B + +struct id_block_tag { + u32 id; + u32 version; + u32 flags; + u16 boot_img_offset; + u8 reserved1[10]; + u32 dev_param[8]; + u8 reserved2[506 - 56]; + u16 data_img_len; + u16 boot_img_len; + u8 reserved3[512 - 510]; +} __packed; + int sfc_init(void __iomem *reg_addr); int sfc_request(struct rk_sfc_op *op, u32 addr, void *data, u32 size); u16 sfc_get_version(void); diff --git a/drivers/rkflash/sfc_nor.c b/drivers/rkflash/sfc_nor.c index d55d891212..2014fed23f 100644 --- a/drivers/rkflash/sfc_nor.c +++ b/drivers/rkflash/sfc_nor.c @@ -578,30 +578,16 @@ static void *snor_flash_info_adjust(struct flash_info *spi_flash_info) return 0; } -int snor_init(struct SFNOR_DEV *p_dev) +static int snor_parse_flash_table(struct SFNOR_DEV *p_dev, + struct flash_info *g_spi_flash_info) { - struct flash_info *g_spi_flash_info; - u32 i, ret; - u8 id_byte[5]; + int i, ret; - if (!p_dev) - return SFC_PARAM_ERR; - - memset((void *)p_dev, 0, sizeof(struct SFNOR_DEV)); - p_dev->max_iosize = sfc_get_max_iosize(); - snor_read_id(id_byte); - rkflash_print_error("sfc nor id: %x %x %x\n", - id_byte[0], id_byte[1], id_byte[2]); - if (0xFF == id_byte[0] || 0x00 == id_byte[0]) - return SFC_ERROR; - - p_dev->manufacturer = id_byte[0]; - p_dev->mem_type = id_byte[1]; - - g_spi_flash_info = snor_get_flash_info(id_byte); if (g_spi_flash_info) { snor_flash_info_adjust(g_spi_flash_info); - p_dev->capacity = 1 << g_spi_flash_info->density; + p_dev->manufacturer = (g_spi_flash_info->id >> 16) & 0xFF; + p_dev->mem_type = (g_spi_flash_info->id >> 8) & 0xFF; + p_dev->capacity = 1 << ((g_spi_flash_info->id & 0xFF) - 9); p_dev->blk_size = g_spi_flash_info->block_size; p_dev->page_size = NOR_SECS_PAGE; p_dev->read_cmd = g_spi_flash_info->read_cmd; @@ -620,6 +606,7 @@ int snor_init(struct SFNOR_DEV *p_dev) p_dev->write_status = snor_write_status1; else if (i == 2) p_dev->write_status = snor_write_status2; + if (g_spi_flash_info->feature & FEA_4BIT_READ) { ret = SFC_OK; if (g_spi_flash_info->QE_bits) @@ -640,7 +627,34 @@ int snor_init(struct SFNOR_DEV *p_dev) if ((g_spi_flash_info->feature & FEA_4BYTE_ADDR_MODE)) snor_enter_4byte_mode(); + } + + return SFC_OK; +} + +int snor_init(struct SFNOR_DEV *p_dev) +{ + struct flash_info *g_spi_flash_info; + u8 id_byte[5]; + + if (!p_dev) + return SFC_PARAM_ERR; + + memset((void *)p_dev, 0, sizeof(struct SFNOR_DEV)); + p_dev->max_iosize = sfc_get_max_iosize(); + + snor_read_id(id_byte); + rkflash_print_error("sfc nor id: %x %x %x\n", + id_byte[0], id_byte[1], id_byte[2]); + if (0xFF == id_byte[0] || 0x00 == id_byte[0]) + return SFC_ERROR; + + g_spi_flash_info = snor_get_flash_info(id_byte); + if (g_spi_flash_info) { + snor_parse_flash_table(p_dev, g_spi_flash_info); } else { + p_dev->manufacturer = id_byte[0]; + p_dev->mem_type = id_byte[1]; p_dev->capacity = 1 << (id_byte[2] - 9); p_dev->QE_bits = 0; p_dev->blk_size = NOR_SECS_BLK; @@ -652,6 +666,7 @@ int snor_init(struct SFNOR_DEV *p_dev) p_dev->prog_lines = DATA_LINES_X1; p_dev->read_lines = DATA_LINES_X1; p_dev->write_status = snor_write_status; + snor_reset_device(); } rkflash_print_info("addr_mode: %x\n", p_dev->addr_mode); @@ -661,7 +676,42 @@ int snor_init(struct SFNOR_DEV *p_dev) rkflash_print_info("prog_cmd: %x\n", p_dev->prog_cmd); rkflash_print_info("blk_erase_cmd: %x\n", p_dev->blk_erase_cmd); rkflash_print_info("sec_erase_cmd: %x\n", p_dev->sec_erase_cmd); + rkflash_print_info("capacity: %x\n", p_dev->capacity); return SFC_OK; } +int snor_reinit_from_table_packet(struct SFNOR_DEV *p_dev, + struct snor_info_packet *packet) +{ + struct flash_info g_spi_flash_info; + u8 id_byte[5]; + int ret; + + if (!p_dev || packet->id != SNOR_INFO_PACKET_ID) + return SFC_PARAM_ERR; + + snor_read_id(id_byte); + if (0xFF == id_byte[0] || 0x00 == id_byte[0]) + return SFC_ERROR; + + g_spi_flash_info.id = id_byte[0] << 16 | id_byte[1] << 8 | id_byte[2]; + g_spi_flash_info.block_size = NOR_SECS_BLK; + g_spi_flash_info.sector_size = NOR_SECS_PAGE; + g_spi_flash_info.read_cmd = packet->read_cmd; + g_spi_flash_info.prog_cmd = packet->prog_cmd; + g_spi_flash_info.read_cmd_4 = packet->read_cmd_4; + g_spi_flash_info.prog_cmd_4 = packet->prog_cmd_4; + if (id_byte[2] >= 0x19) + g_spi_flash_info.read_cmd_4 = CMD_FAST_4READ_X4; + g_spi_flash_info.sector_erase_cmd = packet->sector_erase_cmd; + g_spi_flash_info.block_erase_cmd = packet->block_erase_cmd; + g_spi_flash_info.feature = packet->feature; + g_spi_flash_info.density = id_byte[2] - 9; + g_spi_flash_info.QE_bits = packet->QE_bits; + + ret = snor_parse_flash_table(p_dev, &g_spi_flash_info); + + return ret; +} + diff --git a/drivers/rkflash/sfc_nor.h b/drivers/rkflash/sfc_nor.h index 6c91bb2eaf..e564b8ed1a 100644 --- a/drivers/rkflash/sfc_nor.h +++ b/drivers/rkflash/sfc_nor.h @@ -134,6 +134,30 @@ struct flash_info { u8 reserved2; }; +/* flash table packet for easy boot */ +#define SNOR_INFO_PACKET_ID 0x464E494E +#define SNOR_INFO_PACKET_HEAD_LEN 14 + +#define SNOR_INFO_PACKET_SPI_MODE_RATE_SHIFT 25 + +struct snor_info_packet { + u32 id; + u32 head_hash; /*hash for head, check by bootrom.*/ + u16 head_len; /*320 - 16 bytes*/ + u16 version; + u8 read_cmd; + u8 prog_cmd; + u8 read_cmd_4; + u8 prog_cmd_4; + + u8 sector_erase_cmd; + u8 block_erase_cmd; + u8 feature; + u8 QE_bits; + + u32 spi_mode; +}; + int snor_init(struct SFNOR_DEV *p_dev); u32 snor_get_capacity(struct SFNOR_DEV *p_dev); int snor_read(struct SFNOR_DEV *p_dev, u32 sec, u32 n_sec, void *p_data); @@ -146,5 +170,6 @@ int snor_prog_page(struct SFNOR_DEV *p_dev, u32 addr, void *p_data, u32 size); int snor_read_data(struct SFNOR_DEV *p_dev, u32 addr, void *p_data, u32 size); int snor_reset_device(void); int snor_disable_QE(struct SFNOR_DEV *p_dev); - +int snor_reinit_from_table_packet(struct SFNOR_DEV *p_dev, + struct snor_info_packet *packet); #endif