diff options
author | Rob Purchase <shotofadds@rockbox.org> | 2009-03-02 23:36:12 +0000 |
---|---|---|
committer | Rob Purchase <shotofadds@rockbox.org> | 2009-03-02 23:36:12 +0000 |
commit | 9f6e117e8283ce683efe546b32139dd723c724d1 (patch) | |
tree | 4439fd3dc5836038159aae4569e893b006e1a276 | |
parent | 3fe6152a1a6095e41426709d4a2eb3780529d518 (diff) | |
download | rockbox-9f6e117e8283ce683efe546b32139dd723c724d1.tar.gz rockbox-9f6e117e8283ce683efe546b32139dd723c724d1.zip |
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
-rw-r--r-- | firmware/drivers/nand_id.c | 30 | ||||
-rw-r--r-- | firmware/export/nand_id.h | 5 | ||||
-rw-r--r-- | firmware/target/arm/ata-nand-telechips.c | 128 |
3 files changed, 91 insertions, 72 deletions
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 | |||
31 | 31 | ||
32 | static const struct nand_info samsung[] = | 32 | static const struct nand_info samsung[] = |
33 | { | 33 | { |
34 | /* { id1, id2, pages_per_block, blocks_per_bank, page_size, spare_size, col_cycles, row_cycles } */ | 34 | /* |
35 | 35 | id1, id2 | |
36 | /* K9F4G08UOM */ | 36 | pages/block, blocks, page_size, spare_size, col_cycles, row_cycles, planes |
37 | {0xDC, 0x10, 64, 4096, 2048, 64, 2, 3 }, | 37 | */ |
38 | /* K9K8G08UOM */ | 38 | {0xDC, 0x10, /* K9F4G08UOM */ |
39 | {0xD3, 0x51, 64, 8192, 2048, 64, 2, 3 }, | 39 | 64, 4096, 2048, 64, 2, 3, 1 }, |
40 | /* K9LAG08UOM */ | 40 | |
41 | {0xD5, 0x55, 128, 8192, 2048, 64, 2, 3 }, | 41 | {0xD3, 0x51, /* K9K8G08UOM */ |
42 | /* K9LBG08UOM, K9HBG08U1M, K9MCG08U5M */ | 42 | 64, 8192, 2048, 64, 2, 3, 1 }, |
43 | {0xD7, 0x55, 128, 8192, 4096, 128, 2, 3 }, | 43 | |
44 | {0xD5, 0x14, /* K9GAG08UOM */ | ||
45 | 128, 4096, 4096, 128, 2, 3, 2 }, | ||
46 | |||
47 | {0xD5, 0x55, /* K9LAG08UOM, K9HBG08U1M, K9MCG08U5M */ | ||
48 | 128, 8192, 2048, 64, 2, 3, 4 }, | ||
49 | |||
50 | {0xD7, 0x55, /* K9LBG08UOM */ | ||
51 | 128, 8192, 4096, 128, 2, 3, 4 }, | ||
44 | }; | 52 | }; |
45 | 53 | ||
46 | #define NI(id, x) {id, (struct nand_info*)x, (sizeof(x)/sizeof(struct nand_info))} | 54 | #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[] = | |||
49 | NI(0xEC, samsung), | 57 | NI(0xEC, samsung), |
50 | }; | 58 | }; |
51 | 59 | ||
52 | // -------------------------------------------------------------------------------------------------- | 60 | // ----------------------------------------------------------------------------- |
53 | 61 | ||
54 | struct nand_info* nand_identify(unsigned char data[5]) | 62 | struct nand_info* nand_identify(unsigned char data[5]) |
55 | { | 63 | { |
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 | |||
29 | unsigned short blocks_per_bank; | 29 | unsigned short blocks_per_bank; |
30 | unsigned short page_size; | 30 | unsigned short page_size; |
31 | unsigned short spare_size; | 31 | unsigned short spare_size; |
32 | unsigned short col_cycles; | 32 | unsigned char col_cycles; |
33 | unsigned short row_cycles; | 33 | unsigned char row_cycles; |
34 | unsigned char planes; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | struct nand_info* nand_identify(unsigned char data[5]); | 37 | 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; | |||
44 | 44 | ||
45 | #if defined(COWON_D2) || defined(IAUDIO_7) | 45 | #if defined(COWON_D2) || defined(IAUDIO_7) |
46 | #define FTL_V2 | 46 | #define FTL_V2 |
47 | #define BLOCKS_PER_SEGMENT 4 | ||
48 | #define MAX_WRITE_CACHES 8 | 47 | #define MAX_WRITE_CACHES 8 |
49 | #else | 48 | #else |
50 | #define FTL_V1 | 49 | #define FTL_V1 |
51 | #define BLOCKS_PER_SEGMENT 1 | ||
52 | #define MAX_WRITE_CACHES 4 | 50 | #define MAX_WRITE_CACHES 4 |
53 | #endif | 51 | #endif |
54 | 52 | ||
@@ -87,28 +85,26 @@ static struct mutex ata_mtx SHAREDBSS_ATTR; | |||
87 | 85 | ||
88 | /* Chip characteristics, initialised by nand_get_chip_info() */ | 86 | /* Chip characteristics, initialised by nand_get_chip_info() */ |
89 | 87 | ||
90 | static int page_size = 0; | 88 | static struct nand_info* nand_data = NULL; |
91 | static int spare_size = 0; | 89 | |
92 | static int pages_per_block = 0; | 90 | static int total_banks = 0; |
93 | static int blocks_per_bank = 0; | 91 | static int pages_per_bank = 0; |
94 | static int pages_per_bank = 0; | ||
95 | static int row_cycles = 0; | ||
96 | static int col_cycles = 0; | ||
97 | static int total_banks = 0; | ||
98 | static int sectors_per_page = 0; | 92 | static int sectors_per_page = 0; |
99 | static int bytes_per_segment = 0; | 93 | static int bytes_per_segment = 0; |
100 | static int sectors_per_segment = 0; | 94 | static int sectors_per_segment = 0; |
101 | static int segments_per_bank = 0; | 95 | static int segments_per_bank = 0; |
96 | static int pages_per_segment = 0; | ||
102 | 97 | ||
103 | /* Maximum values for static buffers */ | 98 | /* Maximum values for static buffers */ |
104 | 99 | ||
105 | #define MAX_PAGE_SIZE 4096 | 100 | #define MAX_PAGE_SIZE 4096 |
106 | #define MAX_SPARE_SIZE 128 | 101 | #define MAX_SPARE_SIZE 128 |
107 | #define MAX_BLOCKS_PER_BANK 8192 | 102 | #define MAX_BLOCKS_PER_BANK 8192 |
108 | #define MAX_PAGES_PER_BLOCK 128 | 103 | #define MAX_PAGES_PER_BLOCK 128 |
109 | #define MAX_BANKS 4 | 104 | #define MAX_BANKS 4 |
105 | #define MAX_BLOCKS_PER_SEGMENT 4 | ||
110 | 106 | ||
111 | #define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / BLOCKS_PER_SEGMENT) | 107 | #define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / MAX_BLOCKS_PER_SEGMENT) |
112 | 108 | ||
113 | /* Logical/Physical translation table */ | 109 | /* Logical/Physical translation table */ |
114 | 110 | ||
@@ -134,7 +130,7 @@ struct write_cache | |||
134 | short inplace_pages_used; | 130 | short inplace_pages_used; |
135 | short random_bank; | 131 | short random_bank; |
136 | short random_phys_segment; | 132 | short random_phys_segment; |
137 | short page_map[MAX_PAGES_PER_BLOCK * BLOCKS_PER_SEGMENT]; | 133 | short page_map[MAX_PAGES_PER_BLOCK * MAX_BLOCKS_PER_SEGMENT]; |
138 | }; | 134 | }; |
139 | static struct write_cache write_caches[MAX_WRITE_CACHES]; | 135 | static struct write_cache write_caches[MAX_WRITE_CACHES]; |
140 | 136 | ||
@@ -149,27 +145,41 @@ static unsigned int ecc_fail_count = 0; | |||
149 | 145 | ||
150 | /* Conversion functions */ | 146 | /* Conversion functions */ |
151 | 147 | ||
152 | static inline int phys_segment_to_page_addr(int phys_segment, int page_in_seg) | 148 | static int phys_segment_to_page_addr(int phys_segment, int page_in_seg) |
153 | { | 149 | { |
154 | #if BLOCKS_PER_SEGMENT == 4 /* D2 */ | 150 | int page_addr = 0; |
155 | int page_addr = phys_segment * pages_per_block * 2; | ||
156 | 151 | ||
157 | if (page_in_seg & 1) | 152 | switch (nand_data->planes) |
158 | { | 153 | { |
159 | /* Data is located in block+1 */ | 154 | case 1: |
160 | page_addr += pages_per_block; | 155 | { |
161 | } | 156 | page_addr = (phys_segment * nand_data->pages_per_block); |
157 | break; | ||
158 | } | ||
162 | 159 | ||
163 | if (page_in_seg & 2) | 160 | case 2: |
164 | { | 161 | case 4: |
165 | /* Data is located in second plane */ | 162 | { |
166 | page_addr += (blocks_per_bank/2) * pages_per_block; | 163 | page_addr = phys_segment * nand_data->pages_per_block * 2; |
167 | } | ||
168 | 164 | ||
169 | page_addr += page_in_seg/4; | 165 | if (page_in_seg & 1) |
170 | #elif BLOCKS_PER_SEGMENT == 1 /* M200 */ | 166 | { |
171 | int page_addr = (phys_segment * pages_per_block) + page_in_seg; | 167 | /* Data is located in block+1 */ |
172 | #endif | 168 | page_addr += nand_data->pages_per_block; |
169 | } | ||
170 | |||
171 | if (nand_data->planes == 4 && page_in_seg & 2) | ||
172 | { | ||
173 | /* Data is located in 2nd half of bank */ | ||
174 | page_addr += | ||
175 | (nand_data->blocks_per_bank/2) * nand_data->pages_per_block; | ||
176 | } | ||
177 | |||
178 | break; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | page_addr += (page_in_seg / nand_data->planes); | ||
173 | 183 | ||
174 | return page_addr; | 184 | return page_addr; |
175 | } | 185 | } |
@@ -276,8 +286,8 @@ static void nand_read_uid(int bank, unsigned int* uid_buf) | |||
276 | NFC_CMD = 0x00; | 286 | NFC_CMD = 0x00; |
277 | 287 | ||
278 | /* Write row/column address */ | 288 | /* Write row/column address */ |
279 | for (i = 0; i < col_cycles; i++) NFC_SADDR = 0; | 289 | for (i = 0; i < nand_data->col_cycles; i++) NFC_SADDR = 0; |
280 | for (i = 0; i < row_cycles; i++) NFC_SADDR = 0; | 290 | for (i = 0; i < nand_data->row_cycles; i++) NFC_SADDR = 0; |
281 | 291 | ||
282 | /* End of read */ | 292 | /* End of read */ |
283 | NFC_CMD = 0x30; | 293 | NFC_CMD = 0x30; |
@@ -323,14 +333,14 @@ static void nand_read_raw(int bank, int row, int column, int size, void* buf) | |||
323 | NFC_CMD = 0x00; | 333 | NFC_CMD = 0x00; |
324 | 334 | ||
325 | /* Write column address */ | 335 | /* Write column address */ |
326 | for (i = 0; i < col_cycles; i++) | 336 | for (i = 0; i < nand_data->col_cycles; i++) |
327 | { | 337 | { |
328 | NFC_SADDR = column & 0xFF; | 338 | NFC_SADDR = column & 0xFF; |
329 | column = column >> 8; | 339 | column = column >> 8; |
330 | } | 340 | } |
331 | 341 | ||
332 | /* Write row address */ | 342 | /* Write row address */ |
333 | for (i = 0; i < row_cycles; i++) | 343 | for (i = 0; i < nand_data->row_cycles; i++) |
334 | { | 344 | { |
335 | NFC_SADDR = row & 0xFF; | 345 | NFC_SADDR = row & 0xFF; |
336 | row = row >> 8; | 346 | row = row >> 8; |
@@ -379,7 +389,7 @@ static void nand_get_chip_info(void) | |||
379 | manuf_id = id_buf[0]; | 389 | manuf_id = id_buf[0]; |
380 | 390 | ||
381 | /* Identify the chip geometry */ | 391 | /* Identify the chip geometry */ |
382 | struct nand_info* nand_data = nand_identify(id_buf); | 392 | nand_data = nand_identify(id_buf); |
383 | 393 | ||
384 | if (nand_data == NULL) | 394 | if (nand_data == NULL) |
385 | { | 395 | { |
@@ -387,18 +397,18 @@ static void nand_get_chip_info(void) | |||
387 | id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]); | 397 | id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]); |
388 | } | 398 | } |
389 | 399 | ||
390 | page_size = nand_data->page_size; | 400 | pages_per_bank = nand_data->blocks_per_bank * nand_data->pages_per_block; |
391 | spare_size = nand_data->spare_size; | 401 | |
392 | pages_per_block = nand_data->pages_per_block; | 402 | segments_per_bank = nand_data->blocks_per_bank / nand_data->planes; |
393 | blocks_per_bank = nand_data->blocks_per_bank; | 403 | |
394 | col_cycles = nand_data->col_cycles; | 404 | bytes_per_segment = nand_data->page_size * nand_data->pages_per_block |
395 | row_cycles = nand_data->row_cycles; | 405 | * nand_data->planes; |
396 | 406 | ||
397 | pages_per_bank = blocks_per_bank * pages_per_block; | 407 | sectors_per_page = nand_data->page_size / SECTOR_SIZE; |
398 | segments_per_bank = blocks_per_bank / BLOCKS_PER_SEGMENT; | 408 | |
399 | bytes_per_segment = page_size * pages_per_block * BLOCKS_PER_SEGMENT; | ||
400 | sectors_per_page = page_size / SECTOR_SIZE; | ||
401 | sectors_per_segment = bytes_per_segment / SECTOR_SIZE; | 409 | sectors_per_segment = bytes_per_segment / SECTOR_SIZE; |
410 | |||
411 | pages_per_segment = sectors_per_segment / sectors_per_page; | ||
402 | 412 | ||
403 | /* Establish how many banks are present */ | 413 | /* Establish how many banks are present */ |
404 | nand_read_id(1, id_buf); | 414 | nand_read_id(1, id_buf); |
@@ -447,10 +457,9 @@ static void nand_get_chip_info(void) | |||
447 | This is not present on some older players (formatted with early FW?) | 457 | This is not present on some older players (formatted with early FW?) |
448 | */ | 458 | */ |
449 | 459 | ||
450 | nand_read_raw(0, /* bank */ | 460 | nand_read_raw(0, 0, /* bank, page */ |
451 | 0, /* page */ | 461 | nand_data->page_size, /* offset */ |
452 | page_size, /* offset */ | 462 | 8, id_buf); /* length, dest */ |
453 | 8, id_buf); | ||
454 | 463 | ||
455 | if (strncmp(id_buf, "BMP", 3)) panicf("BMP tag not present"); | 464 | if (strncmp(id_buf, "BMP", 3)) panicf("BMP tag not present"); |
456 | 465 | ||
@@ -611,7 +620,9 @@ static void read_random_writes_cache(int bank, int phys_segment) | |||
611 | #ifndef FTL_V1 | 620 | #ifndef FTL_V1 |
612 | /* Loop over each page in the phys segment (from page 1 onwards). | 621 | /* Loop over each page in the phys segment (from page 1 onwards). |
613 | Read spare for 1st sector, store location of page in array. */ | 622 | Read spare for 1st sector, store location of page in array. */ |
614 | for (page = 1; page < pages_per_block * BLOCKS_PER_SEGMENT; page++) | 623 | for (page = 1; |
624 | page < (nand_data->pages_per_block * nand_data->planes); | ||
625 | page++) | ||
615 | { | 626 | { |
616 | unsigned short cached_page; | 627 | unsigned short cached_page; |
617 | 628 | ||
@@ -663,7 +674,7 @@ static void read_inplace_writes_cache(int bank, int phys_segment) | |||
663 | 674 | ||
664 | /* Find how many pages have been written to the new segment */ | 675 | /* Find how many pages have been written to the new segment */ |
665 | while (log_segment != -1 && | 676 | while (log_segment != -1 && |
666 | page < (pages_per_block * BLOCKS_PER_SEGMENT) - 1) | 677 | page < (nand_data->pages_per_block * nand_data->planes) - 1) |
667 | { | 678 | { |
668 | page++; | 679 | page++; |
669 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), | 680 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), |
@@ -802,10 +813,9 @@ int nand_init(void) | |||
802 | if (type == SECTYPE_MAIN_INPLACE_CACHE) | 813 | if (type == SECTYPE_MAIN_INPLACE_CACHE) |
803 | { | 814 | { |
804 | /* Check last sector of sequential write cache block */ | 815 | /* Check last sector of sequential write cache block */ |
805 | nand_read_raw(bank, | 816 | nand_read_raw(bank, phys_segment_to_page_addr |
806 | phys_segment_to_page_addr(phys_segment, | 817 | (phys_segment, pages_per_segment - 1), |
807 | (pages_per_block * BLOCKS_PER_SEGMENT) - 1), | 818 | nand_data->page_size + nand_data->spare_size - 16, |
808 | page_size + spare_size - 16, | ||
809 | 16, spare_buf); | 819 | 16, spare_buf); |
810 | 820 | ||
811 | /* If last sector has been written, treat block as main data */ | 821 | /* If last sector has been written, treat block as main data */ |