summaryrefslogtreecommitdiff
path: root/firmware/target/arm/ata-nand-telechips.c
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2009-03-02 23:36:12 +0000
committerRob Purchase <shotofadds@rockbox.org>2009-03-02 23:36:12 +0000
commit9f6e117e8283ce683efe546b32139dd723c724d1 (patch)
tree4439fd3dc5836038159aae4569e893b006e1a276 /firmware/target/arm/ata-nand-telechips.c
parent3fe6152a1a6095e41426709d4a2eb3780529d518 (diff)
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
Diffstat (limited to 'firmware/target/arm/ata-nand-telechips.c')
-rw-r--r--firmware/target/arm/ata-nand-telechips.c128
1 files changed, 69 insertions, 59 deletions
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 */