From 9f6e117e8283ce683efe546b32139dd723c724d1 Mon Sep 17 00:00:00 2001 From: Rob Purchase Date: Mon, 2 Mar 2009 23:36:12 +0000 Subject: TCC NAND: The BLOCKS_PER_SEGMENT define was actually the number of planes mentioned in the Samsung NAND datasheet. Add this to the nand_id struct, so that it can be runtime detected (required for some D2s to boot). Use the struct directly instead of making a local copy, and format the nand_info table to 80 columns. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20186 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/nand_id.c | 30 +++++--- firmware/export/nand_id.h | 5 +- firmware/target/arm/ata-nand-telechips.c | 128 +++++++++++++++++-------------- 3 files changed, 91 insertions(+), 72 deletions(-) (limited to 'firmware') diff --git a/firmware/drivers/nand_id.c b/firmware/drivers/nand_id.c index dfb96c8820..f2b9861c7c 100644 --- a/firmware/drivers/nand_id.c +++ b/firmware/drivers/nand_id.c @@ -31,16 +31,24 @@ struct nand_manufacturer static const struct nand_info samsung[] = { -/* { id1, id2, pages_per_block, blocks_per_bank, page_size, spare_size, col_cycles, row_cycles } */ - - /* K9F4G08UOM */ - {0xDC, 0x10, 64, 4096, 2048, 64, 2, 3 }, - /* K9K8G08UOM */ - {0xD3, 0x51, 64, 8192, 2048, 64, 2, 3 }, - /* K9LAG08UOM */ - {0xD5, 0x55, 128, 8192, 2048, 64, 2, 3 }, - /* K9LBG08UOM, K9HBG08U1M, K9MCG08U5M */ - {0xD7, 0x55, 128, 8192, 4096, 128, 2, 3 }, +/* + id1, id2 + pages/block, blocks, page_size, spare_size, col_cycles, row_cycles, planes +*/ + {0xDC, 0x10, /* K9F4G08UOM */ + 64, 4096, 2048, 64, 2, 3, 1 }, + + {0xD3, 0x51, /* K9K8G08UOM */ + 64, 8192, 2048, 64, 2, 3, 1 }, + + {0xD5, 0x14, /* K9GAG08UOM */ + 128, 4096, 4096, 128, 2, 3, 2 }, + + {0xD5, 0x55, /* K9LAG08UOM, K9HBG08U1M, K9MCG08U5M */ + 128, 8192, 2048, 64, 2, 3, 4 }, + + {0xD7, 0x55, /* K9LBG08UOM */ + 128, 8192, 4096, 128, 2, 3, 4 }, }; #define NI(id, x) {id, (struct nand_info*)x, (sizeof(x)/sizeof(struct nand_info))} @@ -49,7 +57,7 @@ static const struct nand_manufacturer all[] = NI(0xEC, samsung), }; -// -------------------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- struct nand_info* nand_identify(unsigned char data[5]) { diff --git a/firmware/export/nand_id.h b/firmware/export/nand_id.h index 188b6c161a..fb7ea18b8d 100644 --- a/firmware/export/nand_id.h +++ b/firmware/export/nand_id.h @@ -29,8 +29,9 @@ struct nand_info unsigned short blocks_per_bank; unsigned short page_size; unsigned short spare_size; - unsigned short col_cycles; - unsigned short row_cycles; + unsigned char col_cycles; + unsigned char row_cycles; + unsigned char planes; }; struct nand_info* nand_identify(unsigned char data[5]); diff --git a/firmware/target/arm/ata-nand-telechips.c b/firmware/target/arm/ata-nand-telechips.c index 60d2211977..6d1d536194 100644 --- a/firmware/target/arm/ata-nand-telechips.c +++ b/firmware/target/arm/ata-nand-telechips.c @@ -44,11 +44,9 @@ static struct mutex ata_mtx SHAREDBSS_ATTR; #if defined(COWON_D2) || defined(IAUDIO_7) #define FTL_V2 -#define BLOCKS_PER_SEGMENT 4 #define MAX_WRITE_CACHES 8 #else #define FTL_V1 -#define BLOCKS_PER_SEGMENT 1 #define MAX_WRITE_CACHES 4 #endif @@ -87,28 +85,26 @@ static struct mutex ata_mtx SHAREDBSS_ATTR; /* Chip characteristics, initialised by nand_get_chip_info() */ -static int page_size = 0; -static int spare_size = 0; -static int pages_per_block = 0; -static int blocks_per_bank = 0; -static int pages_per_bank = 0; -static int row_cycles = 0; -static int col_cycles = 0; -static int total_banks = 0; +static struct nand_info* nand_data = NULL; + +static int total_banks = 0; +static int pages_per_bank = 0; static int sectors_per_page = 0; static int bytes_per_segment = 0; static int sectors_per_segment = 0; static int segments_per_bank = 0; +static int pages_per_segment = 0; /* Maximum values for static buffers */ -#define MAX_PAGE_SIZE 4096 -#define MAX_SPARE_SIZE 128 -#define MAX_BLOCKS_PER_BANK 8192 -#define MAX_PAGES_PER_BLOCK 128 -#define MAX_BANKS 4 +#define MAX_PAGE_SIZE 4096 +#define MAX_SPARE_SIZE 128 +#define MAX_BLOCKS_PER_BANK 8192 +#define MAX_PAGES_PER_BLOCK 128 +#define MAX_BANKS 4 +#define MAX_BLOCKS_PER_SEGMENT 4 -#define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / BLOCKS_PER_SEGMENT) +#define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / MAX_BLOCKS_PER_SEGMENT) /* Logical/Physical translation table */ @@ -134,7 +130,7 @@ struct write_cache short inplace_pages_used; short random_bank; short random_phys_segment; - short page_map[MAX_PAGES_PER_BLOCK * BLOCKS_PER_SEGMENT]; + short page_map[MAX_PAGES_PER_BLOCK * MAX_BLOCKS_PER_SEGMENT]; }; static struct write_cache write_caches[MAX_WRITE_CACHES]; @@ -149,27 +145,41 @@ static unsigned int ecc_fail_count = 0; /* Conversion functions */ -static inline int phys_segment_to_page_addr(int phys_segment, int page_in_seg) +static int phys_segment_to_page_addr(int phys_segment, int page_in_seg) { -#if BLOCKS_PER_SEGMENT == 4 /* D2 */ - int page_addr = phys_segment * pages_per_block * 2; + int page_addr = 0; - if (page_in_seg & 1) + switch (nand_data->planes) { - /* Data is located in block+1 */ - page_addr += pages_per_block; - } + case 1: + { + page_addr = (phys_segment * nand_data->pages_per_block); + break; + } - if (page_in_seg & 2) - { - /* Data is located in second plane */ - page_addr += (blocks_per_bank/2) * pages_per_block; - } + case 2: + case 4: + { + page_addr = phys_segment * nand_data->pages_per_block * 2; - page_addr += page_in_seg/4; -#elif BLOCKS_PER_SEGMENT == 1 /* M200 */ - int page_addr = (phys_segment * pages_per_block) + page_in_seg; -#endif + if (page_in_seg & 1) + { + /* Data is located in block+1 */ + page_addr += nand_data->pages_per_block; + } + + if (nand_data->planes == 4 && page_in_seg & 2) + { + /* Data is located in 2nd half of bank */ + page_addr += + (nand_data->blocks_per_bank/2) * nand_data->pages_per_block; + } + + break; + } + } + + page_addr += (page_in_seg / nand_data->planes); return page_addr; } @@ -276,8 +286,8 @@ static void nand_read_uid(int bank, unsigned int* uid_buf) NFC_CMD = 0x00; /* Write row/column address */ - for (i = 0; i < col_cycles; i++) NFC_SADDR = 0; - for (i = 0; i < row_cycles; i++) NFC_SADDR = 0; + for (i = 0; i < nand_data->col_cycles; i++) NFC_SADDR = 0; + for (i = 0; i < nand_data->row_cycles; i++) NFC_SADDR = 0; /* End of read */ NFC_CMD = 0x30; @@ -323,14 +333,14 @@ static void nand_read_raw(int bank, int row, int column, int size, void* buf) NFC_CMD = 0x00; /* Write column address */ - for (i = 0; i < col_cycles; i++) + for (i = 0; i < nand_data->col_cycles; i++) { NFC_SADDR = column & 0xFF; column = column >> 8; } /* Write row address */ - for (i = 0; i < row_cycles; i++) + for (i = 0; i < nand_data->row_cycles; i++) { NFC_SADDR = row & 0xFF; row = row >> 8; @@ -379,7 +389,7 @@ static void nand_get_chip_info(void) manuf_id = id_buf[0]; /* Identify the chip geometry */ - struct nand_info* nand_data = nand_identify(id_buf); + nand_data = nand_identify(id_buf); if (nand_data == NULL) { @@ -387,18 +397,18 @@ static void nand_get_chip_info(void) id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]); } - page_size = nand_data->page_size; - spare_size = nand_data->spare_size; - pages_per_block = nand_data->pages_per_block; - blocks_per_bank = nand_data->blocks_per_bank; - col_cycles = nand_data->col_cycles; - row_cycles = nand_data->row_cycles; - - pages_per_bank = blocks_per_bank * pages_per_block; - segments_per_bank = blocks_per_bank / BLOCKS_PER_SEGMENT; - bytes_per_segment = page_size * pages_per_block * BLOCKS_PER_SEGMENT; - sectors_per_page = page_size / SECTOR_SIZE; + pages_per_bank = nand_data->blocks_per_bank * nand_data->pages_per_block; + + segments_per_bank = nand_data->blocks_per_bank / nand_data->planes; + + bytes_per_segment = nand_data->page_size * nand_data->pages_per_block + * nand_data->planes; + + sectors_per_page = nand_data->page_size / SECTOR_SIZE; + sectors_per_segment = bytes_per_segment / SECTOR_SIZE; + + pages_per_segment = sectors_per_segment / sectors_per_page; /* Establish how many banks are present */ nand_read_id(1, id_buf); @@ -447,10 +457,9 @@ static void nand_get_chip_info(void) This is not present on some older players (formatted with early FW?) */ - nand_read_raw(0, /* bank */ - 0, /* page */ - page_size, /* offset */ - 8, id_buf); + nand_read_raw(0, 0, /* bank, page */ + nand_data->page_size, /* offset */ + 8, id_buf); /* length, dest */ if (strncmp(id_buf, "BMP", 3)) panicf("BMP tag not present"); @@ -611,7 +620,9 @@ static void read_random_writes_cache(int bank, int phys_segment) #ifndef FTL_V1 /* Loop over each page in the phys segment (from page 1 onwards). Read spare for 1st sector, store location of page in array. */ - for (page = 1; page < pages_per_block * BLOCKS_PER_SEGMENT; page++) + for (page = 1; + page < (nand_data->pages_per_block * nand_data->planes); + page++) { unsigned short cached_page; @@ -663,7 +674,7 @@ static void read_inplace_writes_cache(int bank, int phys_segment) /* Find how many pages have been written to the new segment */ while (log_segment != -1 && - page < (pages_per_block * BLOCKS_PER_SEGMENT) - 1) + page < (nand_data->pages_per_block * nand_data->planes) - 1) { page++; nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), @@ -802,10 +813,9 @@ int nand_init(void) if (type == SECTYPE_MAIN_INPLACE_CACHE) { /* Check last sector of sequential write cache block */ - nand_read_raw(bank, - phys_segment_to_page_addr(phys_segment, - (pages_per_block * BLOCKS_PER_SEGMENT) - 1), - page_size + spare_size - 16, + nand_read_raw(bank, phys_segment_to_page_addr + (phys_segment, pages_per_segment - 1), + nand_data->page_size + nand_data->spare_size - 16, 16, spare_buf); /* If last sector has been written, treat block as main data */ -- cgit v1.2.3