summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc780x
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2008-01-27 18:50:09 +0000
committerRob Purchase <shotofadds@rockbox.org>2008-01-27 18:50:09 +0000
commit637e26e8e4c87e25bcdc5f6793b86d34061e7aae (patch)
tree051d1b4d77130cecc8f5a284d345fda2f4921bfe /firmware/target/arm/tcc780x
parent762ec6ec33101154fb1e50d8f531e3f0618799c1 (diff)
downloadrockbox-637e26e8e4c87e25bcdc5f6793b86d34061e7aae.tar.gz
rockbox-637e26e8e4c87e25bcdc5f6793b86d34061e7aae.zip
D2: Add auto-detection of the SAMSUNG flash chips used in the 2/4/8Gb
models. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16177 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/tcc780x')
-rw-r--r--firmware/target/arm/tcc780x/ata-nand-tcc780x.c205
1 files changed, 141 insertions, 64 deletions
diff --git a/firmware/target/arm/tcc780x/ata-nand-tcc780x.c b/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
index 813172f590..bd7e9bb336 100644
--- a/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
+++ b/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
@@ -38,7 +38,6 @@ static bool initialized = false;
38static long next_yield = 0; 38static long next_yield = 0;
39#define MIN_YIELD_PERIOD 2000 39#define MIN_YIELD_PERIOD 2000
40 40
41
42/* TCC780x NAND Flash Controller */ 41/* TCC780x NAND Flash Controller */
43 42
44#define NFC_CMD (*(volatile unsigned long *)0xF0053000) 43#define NFC_CMD (*(volatile unsigned long *)0xF0053000)
@@ -49,30 +48,30 @@ static long next_yield = 0;
49#define NFC_IREQ (*(volatile unsigned long *)0xF0053060) 48#define NFC_IREQ (*(volatile unsigned long *)0xF0053060)
50#define NFC_RST (*(volatile unsigned long *)0xF0053064) 49#define NFC_RST (*(volatile unsigned long *)0xF0053064)
51 50
51/* NFC_CTRL flags */
52#define NFC_16BIT (1<<26) 52#define NFC_16BIT (1<<26)
53#define NFC_CS0 (1<<23) 53#define NFC_CS0 (1<<23)
54#define NFC_CS1 (1<<22) 54#define NFC_CS1 (1<<22)
55#define NFC_READY (1<<20) 55#define NFC_READY (1<<20)
56 56
57/* Chip characteristics, initialised by nand_get_chip_info() */
57 58
58#if defined(COWON_D2) 59static int page_size = 0;
59/* 60static int spare_size = 0;
60 ===== Temporary D2 testing code ===== 61static int pages_per_block = 0;
62static int total_blocks = 0;
63static int total_pages = 0;
64static int row_cycles = 0;
65static int col_cycles = 0;
66static int total_banks = 0;
61 67
62 (assumes SAMSUNG K9LAG08UOM (2GB) in 1, 2 or 4 banks) 68/* Static page buffer */
63 69
64 Manufacturer Id: {0xec, 0xd5, 0x55, 0x25, 0x68} 70#define MAX_PAGE_SIZE 4096
71#define MAX_SPARE_SIZE 128
65 72
66*/ 73static int page_buf[(MAX_PAGE_SIZE+MAX_SPARE_SIZE)/4];
67#define PAGE_SIZE 2048
68#define SPARE_SIZE 64
69#define PAGES_PER_BLOCK 128
70#define TOTAL_BLOCKS 8192
71#define TOTAL_PAGES (TOTAL_BLOCKS * PAGES_PER_BLOCK)
72#define COL_CYCLES 2
73#define ROW_CYCLES 3
74 74
75static int page_buf[PAGE_SIZE/4];
76 75
77static void nand_chip_select(int chip) 76static void nand_chip_select(int chip)
78{ 77{
@@ -108,10 +107,9 @@ static void nand_chip_select(int chip)
108 } 107 }
109} 108}
110 109
110
111static void nand_read_id(int chip, unsigned char* id_buf) 111static void nand_read_id(int chip, unsigned char* id_buf)
112{ 112{
113 int i;
114
115 /* Enable NFC bus clock */ 113 /* Enable NFC bus clock */
116 BCLKCTR |= DEV_NAND; 114 BCLKCTR |= DEV_NAND;
117 115
@@ -150,7 +148,7 @@ static void nand_read_id(int chip, unsigned char* id_buf)
150} 148}
151 149
152 150
153static void nand_read_uid(int chip) 151static void nand_read_uid(int chip, unsigned int* uid_buf)
154{ 152{
155 int i; 153 int i;
156 154
@@ -177,8 +175,8 @@ static void nand_read_uid(int chip)
177 NFC_CMD = 0x00; 175 NFC_CMD = 0x00;
178 176
179 /* Write row/column address */ 177 /* Write row/column address */
180 for (i = 0; i < COL_CYCLES; i++) NFC_SADDR = 0; 178 for (i = 0; i < col_cycles; i++) NFC_SADDR = 0;
181 for (i = 0; i < ROW_CYCLES; i++) NFC_SADDR = 0; 179 for (i = 0; i < row_cycles; i++) NFC_SADDR = 0;
182 180
183 /* End of read */ 181 /* End of read */
184 NFC_CMD = 0x30; 182 NFC_CMD = 0x30;
@@ -189,7 +187,7 @@ static void nand_read_uid(int chip)
189 /* Copy data to buffer (data repeats after 8 words) */ 187 /* Copy data to buffer (data repeats after 8 words) */
190 for (i = 0; i < 8; i++) 188 for (i = 0; i < 8; i++)
191 { 189 {
192 page_buf[i] = NFC_WDATA; 190 uid_buf[i] = NFC_WDATA;
193 } 191 }
194 192
195 /* Reset the chip back to normal mode */ 193 /* Reset the chip back to normal mode */
@@ -225,14 +223,14 @@ static void nand_read(int chip, int row, int column, int size)
225 NFC_CMD = 0x00; 223 NFC_CMD = 0x00;
226 224
227 /* Write column address */ 225 /* Write column address */
228 for (i = 0; i < COL_CYCLES; i++) 226 for (i = 0; i < col_cycles; i++)
229 { 227 {
230 NFC_SADDR = column & 0xFF; 228 NFC_SADDR = column & 0xFF;
231 column = column >> 8; 229 column = column >> 8;
232 } 230 }
233 231
234 /* Write row address */ 232 /* Write row address */
235 for (i = 0; i < ROW_CYCLES; i++) 233 for (i = 0; i < row_cycles; i++)
236 { 234 {
237 NFC_SADDR = row & 0xFF; 235 NFC_SADDR = row & 0xFF;
238 row = row >> 8; 236 row = row >> 8;
@@ -258,56 +256,38 @@ static void nand_read(int chip, int row, int column, int size)
258 256
259 257
260/* TEMP testing function */ 258/* TEMP testing function */
261#include <string.h>
262#include "lcd.h" 259#include "lcd.h"
263 260
264extern int line; 261extern int line;
265 262static unsigned char str_buf[MAX_PAGE_SIZE];
263
266static void nand_test(void) 264static void nand_test(void)
267{ 265{
268 int i,j,row; 266 int i,j,row;
269 unsigned char id_buf[5]; 267 int pages_per_mb = 1048576/page_size;
270 unsigned char str_buf[PAGE_SIZE];
271 268
272 /* Display ID codes & UID block for each bank */ 269 printf("%d banks", total_banks);
273 for (i = 0; i < 4; i++) 270 printf("* %d pages", total_pages);
274 { 271 printf("* %d bytes per page", page_size);
275 printf("NAND bank %d:", i);
276
277 nand_read_id(i, id_buf);
278
279 printf("ID: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
280 id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]);
281
282 nand_read_uid(i);
283
284 for (j = 0; j < 8; j += 4)
285 {
286 printf("0x%08x 0x%08x 0x%08x 0x%08x",
287 page_buf[j],page_buf[j+1],page_buf[j+2],page_buf[j+3]);
288 }
289
290 line++;
291 }
292 272
293 while (!button_read_device()) {}; 273 while (!button_read_device()) {};
294 274
295 /* Now for fun, scan the raw pages for 'TAG' and display the contents */ 275 /* Now for fun, scan the raw pages for 'TAG' and display the contents */
296 276
297 row = 0; 277 row = 0;
298 while (row < TOTAL_PAGES) 278 while (row < total_pages)
299 { 279 {
300 bool found = false; 280 bool found = false;
301 unsigned char* buf_ptr = (unsigned char*)page_buf; 281 unsigned char* buf_ptr = (unsigned char*)page_buf;
302 282
303 line = 0; 283 line = 0;
304 284
285 if (row % pages_per_mb == 0) printf("%dMb", row/pages_per_mb);
286
305 /* Read a page from chip 0 */ 287 /* Read a page from chip 0 */
306 nand_read(0, row, 0, PAGE_SIZE); 288 nand_read(0, row, 0, page_size);
307
308 if (row % 512 == 0) printf("%dMb", row/512);
309 289
310 for (j = 0; j < PAGE_SIZE; j++) 290 for (j = 0; j < page_size; j++)
311 { 291 {
312 if (buf_ptr[j] == 'T' && buf_ptr[j+1] == 'A' && buf_ptr[j+2] == 'G') 292 if (buf_ptr[j] == 'T' && buf_ptr[j+1] == 'A' && buf_ptr[j+2] == 'G')
313 found = true; 293 found = true;
@@ -320,7 +300,7 @@ static void nand_test(void)
320 printf("Row %d:", row); 300 printf("Row %d:", row);
321 301
322 /* Copy ascii-readable parts out to a string */ 302 /* Copy ascii-readable parts out to a string */
323 for (i = 0; i < PAGE_SIZE; i++) 303 for (i = 0; i < page_size; i++)
324 { 304 {
325 str_buf[i] = ' '; 305 str_buf[i] = ' ';
326 if (buf_ptr[i] > 31 && buf_ptr[i] < 128) 306 if (buf_ptr[i] > 31 && buf_ptr[i] < 128)
@@ -347,7 +327,8 @@ static void nand_test(void)
347 /* Alternate hex display code 327 /* Alternate hex display code
348 for (i = 0; i<112; i+=4) 328 for (i = 0; i<112; i+=4)
349 { 329 {
350 printf("0x%08x 0x%08x 0x%08x 0x%08x",buf[i],buf[i+1],buf[i+2],buf[i+3]); 330 printf("0x%08x 0x%08x 0x%08x 0x%08x",
331 page_buf[i],page_buf[i+1],page_buf[i+2],page_buf[i+3]);
351 } 332 }
352 */ 333 */
353 334
@@ -358,7 +339,101 @@ static void nand_test(void)
358 row++; 339 row++;
359 } 340 }
360} 341}
361#endif 342
343
344static void nand_get_chip_info(void)
345{
346 bool found = false;
347 unsigned char manuf_id;
348 unsigned char id_buf[5];
349
350 /* Read chip id from bank 0 */
351 nand_read_id(0, id_buf);
352
353 manuf_id = id_buf[0];
354
355 switch (manuf_id)
356 {
357 case 0xEC: /* SAMSUNG */
358
359 switch(id_buf[1]) /* Chip Id */
360 {
361 case 0xD5: /* K9LAG08UOM */
362
363 page_size = 2048;
364 spare_size = 64;
365 pages_per_block = 128;
366 total_blocks = 8192;
367 col_cycles = 2;
368 row_cycles = 3;
369
370 found = true;
371 break;
372
373 case 0xD7: /* K9LBG08UOM */
374
375 page_size = 4096;
376 spare_size = 128;
377 pages_per_block = 128;
378 total_blocks = 8192;
379 col_cycles = 2;
380 row_cycles = 3;
381
382 found = true;
383 break;
384 }
385 break;
386 }
387
388 if (!found)
389 {
390 panicf("Unknown NAND: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
391 id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]);
392 }
393
394 total_pages = total_blocks * pages_per_block;
395
396 /* Establish how many banks are present */
397
398 nand_read_id(1, id_buf);
399
400 if (id_buf[0] == manuf_id)
401 {
402 /* Bank 1 is populated, now check if banks 2/3 are valid */
403 nand_read_id(2, id_buf);
404
405 if (id_buf[0] == manuf_id)
406 {
407 /* Bank 2 returned matching id - check if 2/3 are shadowing 0/1 */
408 unsigned int uid_buf0[8];
409 unsigned int uid_buf2[8];
410
411 nand_read_uid(0, uid_buf0);
412 nand_read_uid(2, uid_buf2);
413
414 if (memcmp(uid_buf0, uid_buf2, 32) == 0)
415 {
416 /* UIDs match, assume banks 2/3 are shadowing 0/1 */
417 total_banks = 2;
418 }
419 else
420 {
421 /* UIDs differ, assume banks 2/3 are valid */
422 total_banks = 4;
423 }
424 }
425 else
426 {
427 /* Bank 2 returned differing id - assume 2/3 are junk */
428 total_banks = 2;
429 }
430 }
431 else
432 {
433 /* Bank 1 returned differing id - assume it is junk */
434 total_banks = 1;
435 }
436}
362 437
363 438
364/* API Functions */ 439/* API Functions */
@@ -425,22 +500,24 @@ int ata_soft_reset(void)
425 500
426void ata_enable(bool on) 501void ata_enable(bool on)
427{ 502{
428 #warning function not implemented 503 /* null - flash controller is enabled/disabled as needed. */
429 (void)on; 504 (void)on;
430} 505}
431 506
432int ata_init(void) 507int ata_init(void)
433{ 508{
434 #warning function not implemented 509 if (!initialized)
510 {
511 /* Get chip characteristics and number of banks */
512 nand_get_chip_info();
435 513
436 /* This needs to: 514 /* TODO: Scan all banks for bad blocks */
437 a) establish how many banks are present
438 (using nand_read_id() and nand_read_uid() above)
439 b) scan all banks for bad blocks
440 c) use this info to build a physical->logical address translation
441 (using an as yet unknown scheme)
442 */
443 515
516 /* TODO: Build physical->logical address translation */
517
518 initialized = true;
519 }
520
444 /* TEMP - print out some diagnostics */ 521 /* TEMP - print out some diagnostics */
445 nand_test(); 522 nand_test();
446 523